I am trying to understand Monad and I have the following code
f a b c d =
do one <- a + b
two <- c * d
three <- one + two
return three
The above compiles
but get the an error when I
*Main> f 1 2 3 4 :1:1: No instances for (Num (a0 -> t0), Monad ((->) a0), Monad ((->) t0)) arising from a use of `f' Possible fix: add instance declarations for (Num (a0 -> t0), Monad ((->) a0), Monad ((->) t0)) In the expression: f 1 2 3 4 In an equation for `it': it = f 1 2 3 4 :1:9: No instance for (Num (a0 -> a0 -> t0)) arising from the literal `4' Possible fix: add an instance declaration for (Num (a0 -> a0 -> t0)) In the fourth argument of `f', namely `4' In the expression: f 1 2 3 4 In an equation for `it': it = f 1 2 3 4
I think I would be one step closer to understand Monad if I know why the above code dont work onf 1 2 3 4
The problem is you are confusing wrapped monadic values with pure values.
The first thing to know is that do notation is syntactic sugar for regular function calls (>>=
and >>
). So, it would help to see what your code desugars too.
Lets try something simpler
f a b =
do one <- a + b
return one
This has the same problem as your code, but is simpler. To understand why it doesn't work we ask: what does this actually mean? Well, we can rewrite the <-
symbol using >>=
f a b = (a + b) >>= \x -> return x
(this is not the simplest representation, but makes the point clear)
If you test the following in GHCi
>> :t (>>=)
Monad m => m a -> (a -> m b) -> m b
that is, the function >>=
takes: an argument of type m
of a
and a function from a
to m
of b
and returns a m
of b
.
What about in this code?
(a + b)
Is going to be a number. How about the other half
\x -> return x
Takes an object of type a
and returns an object of type m a
for any a
So, you need to have a number, that is also some sort of monad of something. Can you think of anything like that? It is not clear what this would be, which is a reason to be suspicious that this should type check.
One good way to come to terms with monads is to look at some specific examples.
The Maybe
monad expresses computations that might fail
instance Monad Maybe where
return = Just
(>>=) (Just a) f = f a
(>>=) Nothing _ = Nothing
This lets you say things with a patter like
f args = do x <- functionThatMightFail args
y <- anotherfunctionThatMightFail x
return y
or the same code more simply
f args = do x <- functionThatMightFail args
anotherfunctionThatMightFail x
or perhaps
f args = functionThatMightFail args >>= anotherfunctionThatMightFail
On the other hand the List
monad captures the idea of performing the same function on every element of a list, and then concatenating the results together. Simple examples abound:
f = do x <- [1,2,3,4]
[1..x]
If you understand these ones, play with the State
monad. It helps you get the more general idea that "monads are models of computation." I would then checkout Parsec, and of course, IO
I'm going to disagree with everyone else and say what you're doing almost certainly simply isn't related to monads. You probably just want to use some boring old code like this instead:
f a b c d = three where
one = a + b
two = c * d
three = one + two
or more succinctly:
f a b c d = a + b + c * d
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With