This repository has been archived by the owner on Jan 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathMonadTransformers.hs
59 lines (50 loc) · 1.58 KB
/
MonadTransformers.hs
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
{-# LANGUAGE FlexibleContexts #-}
module MonadTransformers
( Computation
, interpret
, program
) where
{-
- This example solves the challenge in the most standard way: with a monad
- transformer stack. The idea of monad transformers came from [1].
-
- [1] Sheng Liang, Paul Hudak, and Mark Jones. 1995. Monad transformers and
- modular interpreters. In Proceedings of the 22nd ACM SIGPLAN-SIGACT
- symposium on Principles of programming languages (POPL '95). ACM, New
- York, NY, USA, 333-343. DOI=https://doi.org/10.1145/199448.199528
-}
import Control.Monad (replicateM_)
import Control.Monad.Random
( MonadRandom
, Rand
, StdGen
, getRandomR
, mkStdGen
, runRand
)
import Control.Monad.State (MonadState, StateT, get, put, runStateT)
import Control.Monad.Writer (MonadWriter, WriterT, runWriterT, tell)
-- The monad
type Computation = WriterT String (StateT Integer (Rand StdGen))
-- The operations
getRandom :: MonadRandom m => m Integer
getRandom = getRandomR (0, 9)
getAccumulator :: MonadState Integer m => m Integer
getAccumulator = get
setAccumulator :: MonadState Integer m => Integer -> m ()
setAccumulator = put
logOutput :: MonadWriter String m => String -> m ()
logOutput = tell
-- The program
program :: (MonadRandom m, MonadState Integer m, MonadWriter String m) => m ()
program =
replicateM_ 10 $ do
i <- getAccumulator
logOutput (show i ++ "\n")
r <- getRandom
setAccumulator (r + i)
-- An interpreter
interpret :: Computation a -> (a, String)
interpret c =
let ((x, _), _) = runRand (runStateT (runWriterT c) 0) (mkStdGen 0)
in x