2

I am learning about monads in the book 'Learn You a Haskell for Great Good!' by Miran Lipovaca. The following example tries to find all the valid positions a knight in chess can reach from their current position:

moveKnight :: KnightPos -> [KnightPos]
moveKnight (c,r) = do 
  (c', r') <- [(c+2, r-1), (c+2, r+1), (c-2, r-1), (c-2, r+1), 
               (c+1, r-2), (c+1,r+2), (c-1,r-2), (c-1,r+2)
              ]
  guard (c' `elem` [1..8] && r' `elem` [1..8])
  return (c', r')

I am having trouble understanding how the code works. I know that for the following with Maybe:

a <- Just 3

The value in a would be 3. But since a list has multiple elements, how does <- work for lists? What would be the value in (c', r')?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
ceno980
  • 2,003
  • 1
  • 19
  • 37
  • 5
    The body of the function after `(c', r') <- ...` would be executed multiple times, once for each element of the list. All resulting values will be then concatenated to produce another list. This is how the `>>=` operator (the heart of monad) is implemented for lists. – Fyodor Soikin Aug 05 '19 at 01:24
  • 1
    In the list monad, `<-` works as in list comprehensions: ``[(c', r') | (c', r') <- [(c+2, r-1), .....], (c' `elem` [1..8] && r' `elem` [1..8])]``. Do-notation and list comprehensions are essentially different syntaxes for the same thing, in the list monad. – chi Aug 05 '19 at 07:03

0 Answers0