-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMain.hs
131 lines (107 loc) · 4.38 KB
/
Main.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
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
-- option 1 (https://github.com/PiotrJustyna/haskell-anywhere):
-- ./ghci.bat C:\Users\piotr_justyna\Documents\github\programming-in-haskell\part2_chapter12_state_monad_practice_relabelling_trees
-- option 2 (stack):
-- stack ghci
-- option 3 (ghci):
-- ghci
--
-- :load Main
<<<<<<< HEAD
=======
import Control.Applicative
-- State and StateTransformer types and orbiting code copied from the state monad exercise.
>>>>>>> Part 2, Chapter 12, state monad practice, part 3.
type State = Int
newtype StateTransformer a = S (State -> (a, State))
<<<<<<< HEAD
-- Is this weird/clever or am I just tired?
=======
>>>>>>> Part 2, Chapter 12, state monad practice, part 3.
apply :: StateTransformer a -> State -> (a, State)
apply (S transformer) state = transformer state
-- functor
instance Functor StateTransformer where
-- fmap :: (a -> b) -> StateTransformer a -> StateTransformer b
fmap function transformer = S (\state1 ->
let (x, state2) = apply transformer state1 in (function x, state2))
-- applicative
instance Applicative StateTransformer where
-- pure :: a -> StateTransformer a
pure x = S (\y -> (x, y))
-- (<*>) :: StateTransformer (a -> b) -> StateTransformer a -> StateTransformer b
functionStateTransformer <*> valueStateTransformer = S (\state1 ->
let (f, state2) = apply functionStateTransformer state1
(x, state3) = apply valueStateTransformer state2 in (f x, state3))
<<<<<<< HEAD
=======
-- monad
instance Monad StateTransformer where
-- return :: a -> StateTransformer a
return = pure
-- (>>=) :: (StateTransformer a) -> (a -> StateTransformer b) -> (StateTransformer b)
valueStateTransformer >>= function = S (\state1 ->
let (value, state2) = apply valueStateTransformer state1 in apply (function value) state2)
data Tree a = Leaf a | Node (Tree a) (Tree a) deriving Show
>>>>>>> Part 2, Chapter 12, state monad practice, part 3.
main = do
putStrLn "New tree:"
putStrLn . show $ newTree
putStrLn ""
putStrLn "Relabelled new tree - basic approach:"
putStrLn . show . fst $ relabel newTree 0
putStrLn ""
<<<<<<< HEAD
putStrLn "Relabelled new tree, applicative style:"
putStrLn . show $ apply (applicativeRelabel newTree) 0
data Tree a = Leaf a | Node (Tree a) (Tree a) deriving Show
=======
putStrLn "Relabelled new tree - applicative approach:"
putStrLn . show . fst $ apply (relabelApplicativeStyle newTree) 0
putStrLn ""
putStrLn "Relabelled new tree - monadic approach:"
putStrLn . show . fst $ apply (relabelMonadicStyle newTree) 0
>>>>>>> Part 2, Chapter 12, state monad practice, part 3.
newTree :: Tree Char
newTree = Node (Node (Leaf 'a') (Leaf 'b')) (Leaf 'c')
-- "traditional" approach -->
-- I feel this function is not perfectly described in the book,
-- so will try to do a better job here.
-- The function:
-- * assigns an integer to every leaf
-- * once an integer is used, it gets incremented and passed along to the next Tree item
-- that way we have each leaf labelled with a unique integer
relabel :: Tree a -> Int -> (Tree Int, Int)
relabel (Leaf _) n = (Leaf n, n + 1)
relabel (Node left right) n =
(Node relabelledLeftTree relabelledRightTree, nRight)
where
(relabelledLeftTree, nLeft) = relabel left n
(relabelledRightTree, nRight) = relabel right nLeft
<<<<<<< HEAD
-- applicative relabel version
fresh :: StateTransformer Int
fresh = S (\x -> (x, x + 1))
applicativeRelabel :: Tree a -> StateTransformer (Tree Int)
applicativeRelabel (Leaf _) = Leaf <$> fresh
applicativeRelabel (Node left right) = Node <$> applicativeRelabel left <*> applicativeRelabel right
=======
-- <-- "traditional" approach
freshLabel :: StateTransformer Int
freshLabel = S (\n -> (n, n + 1))
-- applicative approach -->
relabelApplicativeStyle :: Tree a -> StateTransformer (Tree Int)
relabelApplicativeStyle (Leaf _) = Leaf <$> freshLabel
relabelApplicativeStyle (Node left right) =
Node <$> (relabelApplicativeStyle left) <*> (relabelApplicativeStyle right)
-- <-- applicative approach
-- monadic approach -->
relabelMonadicStyle :: Tree a -> StateTransformer (Tree Int)
relabelMonadicStyle (Leaf _) = do
label <- freshLabel
return (Leaf label)
relabelMonadicStyle (Node left right) = do
left' <- relabelMonadicStyle left
right' <- relabelMonadicStyle right
return (Node left' right')
-- <-- monadic approach
>>>>>>> Part 2, Chapter 12, state monad practice, part 3.