You can use a list as a Monad. The primary difference between list as monads and other sorts of monads is the behavior of the <- keyword.

 listm.hs 1 main = putStrLn(show(do 2 x <- [1..9] 3 return (2*x))) ```\$ ghc --make listm.hs [1 of 1] Compiling Main             ( listm.hs, listm.o ) Linking listm ... ``` ```\$ ./listm [2,4,6,8,10,12,14,16,18] ```

One of the really interesting tricks you can do with the list monad involves the guard() statement.

 listm2.hs 1 import Monad 2 3 main = putStrLn(show(do 4 x <- [1..9] 5 guard(x `mod` 3 /= 0) 6 return (2*x))) ```\$ ghc --make listm2.hs [1 of 1] Compiling Main             ( listm2.hs, listm2.o ) Linking listm2 ... ``` ```\$ ./listm2 [2,4,8,10,14,16] ```

The guard blocks processing of the items in the list if the condition inside it is met. You can get the same effect using case.

 listm3.hs 1 import Monad 2 3 main = putStrLn(show(do 4 x <- [1..9] 5 case (x `mod` 3 /= 0) of 6 True -> return (2*x) 7 False -> [] 8 )) ```\$ ghc --make listm3.hs [1 of 1] Compiling Main             ( listm3.hs, listm3.o ) Linking listm3 ... ``` ```\$ ./listm3 [2,4,8,10,14,16] ```

Note that "return x" is the same as "[x]" in the context of a list monad.

 listm4.hs 1 import Monad 2 3 main = putStrLn(show(do 4 x <- [1..9] 5 case (x `mod` 3 /= 0) of 6 True -> [2*x] 7 False -> [] 8 )) ```\$ ghc --make listm4.hs [1 of 1] Compiling Main             ( listm4.hs, listm4.o ) Linking listm4 ... ``` ```\$ ./listm4 [2,4,8,10,14,16] ```

For your viewing pleasure, here's a version of the Eight Queens problem implemented using the list monad. Possibly not the most elegant solution -- but you can see that using guards in this case causes much less pain than eight "case ... of" structures.

 q8.hs 1 import Monad 2 3 nocapture p1 [] = True 4 nocapture (x1,y1) ((x2,y2):rest) = 5 if (x1==x2) || (y1==y2) || (x1-x2==y1-y2) || (x1-x2==y2-y1) then 6 False 7 else 8 nocapture (x1,y1) rest 9 10 boards = do 11 q1 <- [(1,i) | i <- [1..8]] 12 q2 <- [(2,i) | i <- [1..8]] 13 guard(nocapture q1 [q2]) 14 q3 <- [(3,i) | i <- [1..8]] 15 guard(nocapture q3 [q2,q1]) 16 q4 <- [(4,i) | i <- [1..8]] 17 guard(nocapture q4 [q3,q2,q1]) 18 q5 <- [(5,i) | i <- [1..8]] 19 guard(nocapture q5 [q4,q3,q2,q1]) 20 q6 <- [(6,i) | i <- [1..8]] 21 guard(nocapture q6 [q5,q4,q3,q2,q1]) 22 q7 <- [(7,i) | i <- [1..8]] 23 guard(nocapture q7 [q6,q5,q4,q3,q2,q1]) 24 q8 <- [(8,i) | i <- [1..8]] 25 guard(nocapture q8 [q7,q6,q5,q4,q3,q2,q1]) 26 [q1,q2,q3,q4,q5,q6,q7,q8] 27 28 main = putStrLn(show(take 8 boards)) ```\$ ghc --make q8.hs [1 of 1] Compiling Main             ( q8.hs, q8.o ) Linking q8 ... ``` ```\$ ./q8 [(1,1),(2,5),(3,8),(4,6),(5,3),(6,7),(7,2),(8,4)] ```
 prev next