-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path35monads.hs
180 lines (104 loc) · 4.12 KB
/
35monads.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
{-
How would you write a single IO action that
reads in a number from the user,
doubles it,
and prints that value back to the user,
without using do-notation?
-}
-- revision:
challenge :: IO ()
challenge = do
j <- read <$> getLine -- read converts IO String, to IO Int (via type infrence). <- is used because an IO type is returned
let mysum = j * 2 -- let is used because IO is not returned
let statement = show mysum
putStrLn statement
-- Combine readInt and printDouble (defined next) into a single IO action:
readInt :: IO Int
readInt = read <$> getLine
printDouble :: Int -> IO ()
printDouble n = print (n*2)
readAndPrintDub = readInt >>= printDouble
{-Turn (+ 2) from type Num a => a -> a
to type Num a => a -> IO a using a lambda and return.
Use :t in GHCi to double-check that you’re getting the correct type.-}
plus2 = (+ 2)
plus2' :: Integer -> IO Integer
plus2' = ( \ x -> return (plus2 x))
---
-- read a string as an int
y :: IO Int
y = read <$> getLine
{-To demonstrate how you tie all these together,
let’s write a simple IO action that will ask a user’s name,
and then print out "Hello, <NAME>!".-}
helloName name = "Hello " ++ name ++ "!"
helloNameIO :: String -> IO String
helloNameIO = (\x -> return (helloName x))
-- (>>=) :: m a -> (a -> m b) -> m b
-- (>>) :: m a -> m b -> m b
soln = (>>) (putStrLn "Enter name") (getLine >>= helloNameIO)
-- Exercises:
{-
To prove that Monad is strictly more powerful than Functor,
write a universal version of <$>, as in the preceding lesson’s exercise,
called allFmapM, that defines <$> for all members of the Monad type class.
Because it works for all instances of Monad,
the only functions you can use are the methods required by the Monad type class (and lambda functions).
To get you started, here’s your type signature:
allFmapM :: Monad m => (a -> b) -> m a -> m b
-- (>>=) :: m a -> (a -> m b) -> m b
-}
allFmapM :: Monad m => (a -> b) -> m a -> m b
allFmapM func typeInAContext = (>>=) typeInAContext ( \ x -> return (func x))
{-
To prove that Monad is strictly more powerful than Applicative,
write a universal version of <*>, called allApp,
that defines <*> for all members of the Monad type class.
Because it works for all instances of Monad,
the only functions you can use are the methods required by the Monad type class
(and lambda functions).
To get you started, here’s your type signature:
allApp :: Monad m => m (a -> b) -> m a -> m b
Remember,
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(<*>) :: f (a -> b) -> f a -> f b
(<$>) :: Functor f => (a -> b) -> f a -> f b
(target) :: Monad m => m (a -> b) -> m a -> m b
Try to think exclusively in terms of the type signatures.
Use <$> if you want and replace it with your answer to Q29.1
----
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
{-# MINIMAL (>>=) #-}
-}
-- not sure how to implement
-- allApp funcInAConext typeInAContext = (>>=) typeInAContext customLambda
-- where customLambda func = ( \x -> return funcInAConext x)
{-
Implement a bind function which is the same as (>>=) for Maybe:
bind :: Maybe a -> (a -> Maybe b) -> Maybe b
-}
bind :: (Maybe a) -> (a -> Maybe b) -> Maybe b
bind value fun = (>>=) value fun
----------------------------------------------------
----------------------------------------------------
----------------------------------------------------
{-- 29.1
To prove that Applicative is strictly more powerful than Functor,
write a universal version of fmap, called allFmap,
that defines fmap for all members of the Applicative type class.
Because it works for all instances of Applicative,
the only functions you can use are the methods required by the Applicative type class.
To get you started, here’s your type signature:
allFmap :: Applicative f => (a -> b) -> f a -> f b
-
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
GHC.Base.liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
--
--}
allFmap2 :: Applicative f => (a -> b) -> f a -> f b
allFmap2 normalFunc typeInAContext = pure ( normalFunc ) <*> typeInAContext