MonadPrimer
Jump to navigation
Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
A Monad Primer
#!/usr/bin/env runhaskell
module Main where
import Control.Applicative
import Control.Monad
-- A crib of common monads, their behavior, and how helper functions
-- behave when operating on them.
-- Includes functions from Monad, Applicative and Functor.
main = do
-- Maybe a
-- optional a value.
putStrLn "----- Maybe a -----"
print (return 3 :: Maybe Int) -- Just 3
print (pure 3 :: Maybe Int) -- Just 3
print (Just 3 >>= \n -> Just (n+1)) -- Just 4
print (Just 3 >>= return.(+1)) -- Just 4
print (Nothing >>= return.(+1)) -- Nothing
print (return.(+1) =<< Just 3) -- Just 4
print (join (Just (Just 3))) -- Just 3
print (join (Just Nothing) :: Maybe Int) -- Nothing
print (liftM (+1) (Just 3)) -- Just 4
print (liftA (+1) (Just 3)) -- Just 4
print ((+1) `fmap` Just 3) -- Just 4
print ((+1) `fmap` Nothing) -- Nothing
print (return (+ 1) `ap` Just 3) -- Just 4
print (Just (+ 1) `ap` Just 3) -- Just 4
print (Nothing `ap` Just 3 :: Maybe Int) -- Nothing
print ((+ 1) <$> Just 3) -- Just 4
print ((+ 1) <$> Nothing :: Maybe Int) -- Nothing
print (liftM2 (+) (Just 3) (Just 4)) -- Just 7
print (liftA2 (+) (Just 3) (Just 4)) -- Just 7
print (return (+) `ap` Just 3 `ap` Just 4) -- Just 7
print ((+) `fmap` Just 3 `ap` Just 4) -- Just 7
print ((+) <$> Just 3 <*> Just 4) -- Just 7
print ((+) <$> Nothing <*> Just 4) -- Nothing
print ((+) <$> Just 3 <*> Nothing) -- Nothing
print (guard True >> Just 3) -- Just 3
print (guard False >> Just 3) -- Nothing
print (mapM (\n -> guard (n<10) >> Just (n+2)) [2..4]) -- Just [4,5,6]
print (mapM (\n -> guard (n<10) >> Just (n+2)) [8..14]) -- Nothing
print (forM [2..4] (\n -> guard (n<10) >> Just (n+2)) ) -- Just [4,5,6]
print (foldM (\n m -> guard (n<10) >> Just (n+m)) 1 [2..4]) -- Just 10
print (foldM (\n m -> guard (n<10) >> Just (n+m)) 5 [2..4]) -- Nothing
print (sequence [Just 5, Just 6, Just 7]) -- Just [5,6,7]
print (sequence [Just 5, Nothing, Just 7]) -- Nothing
-- [a]
-- lists of a.
putStrLn "----- [a] -----"
print (return 3 :: [Int]) -- [3]
print (pure 3 :: [Int]) -- [3]
print ([3] >>= \n -> [n+1]) -- [4]
print ([3] >>= return.(+1)) -- [4]
print ([] >>= return.(+1)) -- []
print ([3] >>= \n -> [n+1,n+10]) -- [4,13]
print ([3,5] >>= \n -> [n+1,n+10]) -- [4,13,6,15]
print (return.(+1) =<< [3]) -- [4]
print (join [[3]]) -- [3]
print (join [[3],[4,5],[6,7,8]]) -- [3,4,5,6,7,8]
print (join [[]] :: [Int]) -- []
print (join [] :: [Int]) -- []
print (liftM (+1) [3]) -- [4]
print (liftA (+1) [3]) -- [4]
print ((+1) `fmap` [3]) -- [4]
print ((+1) `fmap` []) -- []
print ((+1) `fmap` [3,30,300]) -- [4,31,301]
print (return (+1) `ap` [3]) -- [4]
print ([(+1)] `ap` [3]) -- [4]
print ([] `ap` [3] :: [Int]) -- []
print ([(+1),(+10)] `ap` [3]) -- [4,13]
print ((+ 1) <$> [3]) -- [4]
print ((+ 1) <$> [3,10,20]) -- [4,11,21]
print ((+ 1) <$> [] :: [Int]) -- []
print (liftM2 (+) [3] [4]) -- [7]
print (liftA2 (+) [3] [4]) -- [7]
print (return (+) `ap` [3] `ap` [4]) -- [7]
print ((+) `fmap` [3] `ap` [4]) -- [7]
print ((+) <$> [3] <*> [4]) -- [7]
print ((+) <$> [3,10] <*> [4,20]) -- [7,23,14,30]
print ((+) <$> [] <*> [4,20]) -- []
print ((+) <$> [3,10] <*> []) -- []
print (guard True >> [1,2,3]) -- [1,2,3]
print (guard False >> [1,2,3]) -- []
print (mapM (\n -> [n+1,n+2]) [10,20]) -- [[11,21],[11,22],[12,21],[12,22]]
print (forM [10,20] (\n -> [n+1,n+2])) -- [[11,21],[11,22],[12,21],[12,22]]
print (foldM (\n m -> [n+m,m+1]) 5 [10]) -- [15,11]
print (foldM (\n m -> [n+m,m+1]) 5 [10,100]) -- [115,101,111,101]
print (sequence [[5], [6,7,8], [9]]) -- [[5,6,9],[5,7,9],[5,8,9]]
print (sequence [[5], [], [9]]) -- []
-- XXX foldM
-- XXX Error/(Either String) a?
-- ((->) a)
-- functions which take an argument of type a.
putStrLn "----- ((->) a) -----"
let testEnv f = print (f 100)
testEnv (const 3) -- 3
testEnv (return 3) -- const 3 -> 3
testEnv (pure 3) -- const 3 -> 3
testEnv (const 3 >>= \n -> (+n)) -- (+3) -> 103
testEnv (*2) -- 200
testEnv ((*2) >>= \n -> (+n)) -- (\n -> n*2 + n) -> 300
testEnv ((\n -> (+n)) =<< const 3) -- (+3) -> 103
-- join :: (a->a-> ...) -> (a -> ...)
testEnv (join (+)) -- (\n -> n+n) -> 200
testEnv (join (*)) -- (\n -> n*n) -> 10000
testEnv (join (const (const 3))) -- const 3 -> 3
testEnv (liftM (+1) (const 3)) -- (+1).(const3) -> 4
testEnv (liftA (+1) (const 3)) -- (+1).(const3) -> 4
testEnv ((+1) `fmap` const 3) -- (+1).(const 3) -> 4
testEnv ((+1) `fmap` (*2)) -- (+1).(*2) -> 201
testEnv (return (+1) `ap` const 3) -- (+1).(const3) -> 4
testEnv ((+1) <$> const 3) -- (+1).(const3) -> 4
testEnv (liftM2 (+) (*2) (*3)) -- (\n -> n*2 + n*3) -> 500
testEnv (liftA2 (+) (*2) (*3)) -- (\n -> n*2 + n*3) -> 500
testEnv (return (+) `ap` (*2) `ap` (*3)) -- (\n -> n*2 + n*3) -> 500
testEnv ((+) `fmap` (*2) `ap` (*3)) -- (\n -> n*2 + n*3) -> 500
testEnv ((+) <$> (*2) <*> (*3)) -- (\n -> n*2 + n*3) -> 500
-- no guard
testEnv (sequence [(*2),(+1),(`div`2)]) -- (\n -> [n*2, n+1, n `div` 2] -> [200,101,50]
testEnv (mapM (\n -> (+n)) [3,4,5]) -- (\n -> [n+3, n+4, n+5) -> [103,104,105]
testEnv (forM [3,4,5] (\n -> (+n))) -- (\n -> [n+3, n+4, n+5) -> [103,104,105]
-- XXX foldM
-- XXX (State s) a
-- Stateful computations.
-- IO a
-- IO operations with results of type a.
putStrLn "----- IO a -----"
-- Two example IO actions returning integers.
-- Assumes /tmp/val1 contains "5" and /tmp/val2 contains "10"
let ex1 :: IO Int
ex1 = liftM read (readFile "/tmp/val1")
ex2 :: Int -> IO Int
ex2 n = liftM ((+n).read) (readFile "/tmp/val2")
testIO :: Show a => IO a -> IO ()
testIO = (>>= print)
testIO (return 3) -- 3
testIO (pure 3) -- 3
testIO (ex1) -- 5
testIO (ex1 >>= ex2) -- 15
testIO (ex2 =<< ex1) -- 15
-- somewhat contrived
-- join :: IO (IO a) -> IO a
testIO (join (return ex1)) -- 5
testIO (liftM (+1) ex1) -- 6
testIO (liftA (+1) ex1) -- 6
testIO ((+1) `fmap` ex1) -- 6
testIO ((+1) `fmap` ex2 1) -- 12
testIO (return (+1) `ap` ex1) -- 6
testIO ((+1) <$> ex1) -- 6
testIO (liftM2 (+) ex1 (ex2 1)) -- 16
testIO (liftA2 (+) ex1 (ex2 1)) -- 16
testIO (return (+) `ap` ex1 `ap` ex2 1) -- 16
testIO ((+) `fmap` ex1 `ap` ex2 1) -- 16
testIO ((+) <$> ex1 <*> ex2 1) -- 16
-- no guard
testIO (mapM ex2 [3,4,5]) -- [13,14,15]
testIO (forM [3,4,5] ex2) -- [13,14,15]
testIO (sequence [ex1, ex2 0]) -- [5,10]
-- XXX foldM