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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
module StateScratch where
--------------------------------------------------------------------------------
import System.Random
-- import Control.Monad.Trans.State
import Data.Function ((&))
import qualified Control.Applicative as Ap
import qualified Control.Monad as M
--------------------------------------------------------------------------------
data Die
= DieOne
| DieTwo
| DieThree
| DieFour
| DieFive
| DieSix
deriving (Eq, Show)
intToDie :: Integer -> Maybe Die
intToDie 1 = Just DieOne
intToDie 2 = Just DieTwo
intToDie 3 = Just DieThree
intToDie 4 = Just DieFour
intToDie 5 = Just DieFive
intToDie 6 = Just DieSix
intToDie _ = Nothing
rollDie :: Moi StdGen Die
rollDie = do
(n, s) <- randomR (1, 6)
case intToDie n of
Just d -> pure (d, s)
Nothing -> pure (DieOne, s)
rollsToGetN :: Integer -> StdGen -> [Die]
rollsToGetN n g = go 0 [] g
where
go sum result gen
| sum >= n = result
| otherwise =
let (dice, nextGen) = randomR (1, 6) gen
in case intToDie dice of
Nothing -> go (sum + dice) result nextGen
Just d -> go (sum + dice) (d : result) nextGen
--------------------------------------------------------------------------------
newtype Moi s a = Moi { runMoi :: s -> (a, s) }
instance Functor (Moi s) where
fmap f (Moi run) =
Moi $ \s -> let (x, t) = run s
in (f x, t)
instance Applicative (Moi s) where
pure x = Moi $ \s -> (x, s)
(Moi f) <*> (Moi run) =
Moi $ \s -> let (g, t) = f s
(x, u) = run t
in (g x, u)
instance Monad (Moi s) where
(Moi run1) >>= f =
Moi $ \s -> let (x, t) = run1 s
(Moi run2) = f x
in run2 t
--------------------------------------------------------------------------------
fizzBuzz :: Integer -> String
fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 5 == 0 = "Buzz"
| n `mod` 3 == 0 = "Fizz"
| otherwise = show n
--------------------------------------------------------------------------------
get :: Moi s s
get = Moi $ \s -> (s, s)
put :: s -> Moi s ()
put x = Moi $ \s -> ((), x)
exec :: Moi s a -> s -> s
exec (Moi run) x = x & run & snd
eval :: Moi s a -> s -> a
eval (Moi run) x = x & run & fst
modify :: (s -> s) -> Moi s ()
modify f = Moi $ \s -> ((), f s)
|