1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
module Exercises where
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Reader (Reader(..), ReaderT(..), runReader, runReaderT)
import Control.Monad.Trans.State (StateT(..))
import Data.Functor.Identity (Identity(..))
-- 1. rDec is a function that should get its argument in the context of
-- Reader and return a value decremented by one.
--
-- Note that “Reader” from transformers is ReaderT of Identity and
-- that runReader is a convenience function throwing away the
-- meaningless structure for you. Play with runReaderT if you like.
rDec :: Num a => Reader a a
rDec = ReaderT $ dec
where dec :: Num a => a -> Identity a
dec = return . (flip (-) 1)
-- 2. Once you have an rDec that works, make it and any inner lamb-
-- das pointfree if that’s not already the case.
-- 3. rShow is show, but in Reader.
rShow :: Show a => Reader a String
rShow = ReaderT $ toString
where toString = return . show
-- 4. Once you have an rShow that works, make it pointfree.
-- 5. rPrintAndInc will first print the input with a greeting, then return
-- the input incremented by one.
rPrintAndInc :: (Num a, Show a) => ReaderT a IO a
rPrintAndInc = ReaderT print
where print x = do
liftIO $ putStrLn $ "Hi: " ++ show x
return $ x + 1
-- Prelude> runReaderT rPrintAndInc 1
-- Hi: 1
-- 2
-- Prelude> traverse (runReaderT rPrintAndInc) [1..10]
-- Hi: 1
-- Hi: 2
-- Hi: 3
-- Hi: 4
-- Hi: 5
-- Hi: 6
-- Hi: 7
-- Hi: 8
-- Hi: 9
-- Hi: 10
-- [2,3,4,5,6,7,8,9,10,11]
-- 6. sPrintIncAccum first prints the input with a greeting, then puts
-- the incremented input as the new state, and returns the original
-- input as a String.
sPrintIncAccum :: (Num a, Show a) => StateT a IO String
sPrintIncAccum = StateT print
where print x = do
liftIO $ putStrLn $ "Hi: " ++ show x
return $ (show x, x + 1)
-- Prelude> runStateT sPrintIncAccum 10
-- Hi: 10
-- ("10",11)
-- Prelude> mapM (runStateT sPrintIncAccum) [1..5]
-- Hi: 1
-- Hi: 2
-- Hi: 3
-- Hi: 4
-- Hi: 5
-- [("1",2),("2",3),("3",4),("4",5),("5",6)]
|