I have some confusion with the function monad. The function monad is defined as follow:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
I tried to play around with it by writing a binding operation:
( (*2) >>= (+10) ) 3
(return 3) :: ((->) Int)
But it caused errors. And I also try to rewrite a function AddStuff into the binding operations.
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
then convert this function into
addStuff' w = (*2) w >>= (\a ->
(+10) w >>= (\b ->
return (a+b) ))
I check the type of the new function as see
addStuff :: (Monad m, Num (m b), Num b) => m b -> m b
Why is that? How can I fix that?
In addStuff' you write (*2) w and (+10) w. Those are equivalent to w*2 and w+10 respectively. So addStuff' is equivalent to this:
addStuff' w = w*2 >>= \a ->
w+10 >>= \b ->
return (a+b)
Writing it this way should make it obvious that here the left operands to >>= are numbers, not functions. That's why the inferred type is telling you that your function only works for numbers that are monads.
When eliminating do notation the left operand to >>= should be exactly the same as the right operand of <-. Also eliminating do notation does not add any arguments to the function. So the correct rewriting would look like this:
addStuff' = (*2) >>= \a ->
(+10) >>= \b ->
return (a+b)
As to why your earlier pieces of code don't work:
( (*2) >>= (+10) ) 3
The operator >>= has type m a -> (a -> m b) -> m b. For simplicity let's assume that all the numbers in this code have type Int, then your left operand has type Int -> Int or m Int if m is (->) Int. So for some type b the right operand should have type Int -> ((->) Int) b or, more readably, Int -> Int -> b. The type it actually has though is Int -> Int. Therefore your expression is ill-typed.
(return 3) :: ((->) Int)
((->) Int) has kind * -> * - the type of a value must have kind *.
Or to approach this differently: return 3 has type m Int for some m (still assuming that all integer literals have type Int for simplicity). So if m is ((->) Int), the type of return 3 will be ((->) Int) Int or Int -> Int, not ((->) Int).
Related
I am writing a Monad that composes functions, f and g, based on this explanation of Monads (https://www.youtube.com/watch?v=ZhuHCtR3xq8). the explanation stops at a crucial part: to compose a function (say f) a -> ma with another (say g) a -> ma, you need a way to convert ma to a, to take stuff out of the monad container (otherwise how could you feed the output of f into g??) and that is not addressed.
assume we have f and g that map an Integer and return a Maybe:
f :: Int -> Maybe Int
f = \x -> (Just x)
g :: Int -> Maybe Int
g = \x -> (Just x)
I want to make a Monad that allows me to compose f and g, so that (g o f)(x) (meaning f(g(x))) can be evaluated. for this to work we need a way to convert Maybe Int (the output of f) into Int so it can be sent to g. when the Maybe container has a value in it, we just pull out the value. when g's output is Nothing, we can consider the value 0 (I know g's output can't be Nothing the g above but lets assume it could for another f).
this is my failed attempt to define a Monad MyMonad that does this:
f :: Int -> Maybe Int
f = \x -> (Just x)
g :: Int -> Maybe Int
g = \x -> (Just x)
data MyMonad a = Maybe a
instance Monad MyMonad where
return x = MyMonad x
Just x >>= (\x -> MyMonad (Just x))
Nothing >>= (\x -> MyMonad (Just 0))
can someone clarify what is wrong here? from tutorials it's very hard to know what the right way to pattern match inside functions is (to handle case of Just vs. Nothing here) and to tease apart all the different syntaxes of instantiating a Monad. this example doesn't help (https://wiki.haskell.org/All_About_Monads#Maybe_a_monad): after introducing bind >>= the sheep example doesn't even use it and uses a combinator instead.
When you first start learning monads, the easiest one to learn is called the Identity monad. It looks like this is what you're actually trying to implement, but you're getting the word Maybe stuck in there somewhere, and it's throwing everything off. (That, or you actually are trying to implement the Maybe monad, but you've not defined Just or Nothing anywhere.)
If MyMonad is like the Identity monad, the correct definition would be:
f :: Int -> MyMonad Int
f = \x -> MyIdentity x
g :: Int -> MyMonad Int
g = \x -> MyIdentity x
data MyMonad a = MyIdentity a
instance Monad MyMonad where
return x = MyIdentity x -- return = \x -> MyIdentity x
(MyIdentity x) >>= f = f x -- (>>=) = \(MyIdentity x) f -> f x
If MyMonad is like the Maybe monad, the correct definition would be:
f :: Int -> MyMonad Int
f = \x -> MyJust x
g :: Int -> MyMonad Int
g = \x -> MyJust x
data MyMonad a = MyNothing | MyJust a
instance Monad MyMonad where
return x = MyJust x
(MyJust x) >>= f = f x
MyNothing >>= f = MyNothing
(Note, for these to compile, you need to also define an instance for Functor and Applicative.)
P.S. To define >>= for the Maybe monad using lambda notation, you'll need a case expression:
(>>=) = \m f -> case m of
MyJust x -> f x
MyNothing -> MyNothing
I think you are looking for the fish (>=>) operator (i'd seen it was called fish at some places but nothing serious about the name). If i am not mistaken you want to compose two functions each taking a binary value to return a monadic value. So let's find the type of our compositing function
(a -> m b) -> (b -> m c) -> (a -> mc)
which happens to be >=> in Control.Monad.
so
f :: Int -> Maybe Int
f = \x -> (Just x)
g :: Int -> Maybe Int
g = \x -> (Just x)
f >=> g $ 10
Just 10
or
f :: Int -> [Int]
f = \x -> replicate x x
g :: Int -> [Maybe Int]
g = \x -> [Just x]
f >=> g $ 10
[Just 10,Just 10,Just 10,Just 10,Just 10,Just 10,Just 10,Just 10,Just 10,Just 10]
You also have another fish <=< swimming to left which is the flipped version of >=>.
Let's consider:
f :: Int
f = return 64 >>= (\x -> x^2) >>= (\y -> y^2)
GHCi rejects my code with
Couldn't match expected type `Int' with actual type `m0 b0'
In the expression: return 64 >>= (\ x -> x ^ 2) >>= (\ y -> y ^ 2)
In an equation for `f':
f = return 64 >>= (\ x -> x ^ 2) >>= (\ y -> y ^ 2)
Failed, modules loaded: none.
The result should be or at least related to 281,474,976,710,656 (64 squared followed by raising the result to the fourth power).
I cannot solve this problem. And it is connected with my misunderstanding of monads. Please help.
We need to look at (>>=). It has type
(>>=) :: Monad m => m a -> (a -> m b) -> m b
In english: the second argument of (>>=) must be function that produces a monadic value. Your functions just produce numbers.
The confusion comes about because you state that f will be an Int. Yet the compiler knows that (>>=) will return a m b
Thus the error message: because of your annotation it expected to find Int, but all it got was m0 b0
Note that your code for f could be correct for a type that is both a number with a sensible implementation of (^) and a monad. But Int is not such a type.
What you want is probably:
f = return 64 >>= pure . (^2) >>= pure . (^4)
or
f = (\x -> (x^2)^4) <$> return 64
But this will still not be a plain Int but an Int in some monad! Thus:
f :: Monad m => m Int
(I think you'll have to turn off the monomorphism restriction to make this actually compile.)
Looking at Haskell's bind:
Prelude> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
I was confused by the following example:
Prelude> let same x = x
Prelude> [[1]] >>= \x -> same x
[1]
Looking at >>='s signature, how does \x -> same x type check with a -> m b?
I would've expected \x -> same x to have produced a [b] type, since the Monad m type here is [], as I understand.
You say
I would've expected \x -> same x to have produced a [b] type, since the Monad m type here is [], as I understand.
and so it does because it is.
We have
[[1]] >>= \ x -> same x
=
[[1]] >>= \ x -> x
[[Int]] [Int] -> [Int] :: [Int]
[] [Int] [Int] -> [] Int :: [] Int
m a a m b m b
Sometimes [] is describing a kind of "nondeterminism" effect. Other times, [] is describing a container-like data structure. The fact that it's difficult to tell the difference between which of these two purposes is being served is a feature of which some people are terribly proud. I'm not ready to agree with them, but I see what they're doing.
Looking at >>='s signature, how does \x -> same x type check with a -> m b?
It's actually very simple. Look at the type signatures:
same :: x -> x
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(>>= same) :: Monad m => m a -> (a -> m b) -> m b
|________|
|
x -> x
Therefore:
x := a
-- and
x := m b
-- and by transitivity
a := x := m b
-- or
a := m b
Hence:
(>>= same) :: Monad m => m (m b) -> m b
This is just the join function from the Control.Monad module, and for the list monad it is the same as the concat function. Thus:
[[1]] >>= \x -> same x
-- is the same as the following via eta reduction
[[1]] >>= same
-- is the same as
(>>= same) [[1]]
-- is the same as
join [[1]]
-- is the same as
concat [[1]]
-- evaluates to
[1]
I would've expected \x -> same x to have produced a [b] type, since the Monad m type here is [], as I understand.
Indeed, it does. The \x -> same x function which has the type x -> x is specialized to the type [b] -> [b] as I explained above. Hence, (>>= same) is of the type [[b]] -> [b] which is the same as the concat function. It flattens a list of lists.
The concat function is a specialization of the join function which flattens a nested monad.
It should be noted that a monad can be defined in terms of either >>= or fmap and join. To quote Wikipedia:
Although Haskell defines monads in terms of the return and >>= functions, it is also possible to define a monad in terms of return and two other operations, join and fmap. This formulation fits more closely with the original definition of monads in category theory. The fmap operation, with type Monad m => (a -> b) -> m a -> m b, takes a function between two types and produces a function that does the “same thing” to values in the monad. The join operation, with type Monad m => m (m a) -> m a, “flattens” two layers of monadic information into one.
The two formulations are related as follows:
fmap f m = m >>= (return . f)
join n = n >>= id
m >>= g ≡ join (fmap g m)
Here, m has the type Monad m => m a, n has the type Monad m => m (m a), f has the type a -> b, and g has the type Monad m => a -> m b, where a and b are underlying types.
The fmap function is defined for any functor in the category of types and functions, not just for monads. It is expected to satisfy the functor laws:
fmap id ≡ id
fmap (f . g) ≡ (fmap f) . (fmap g)
The return function characterizes pointed functors in the same category, by accounting for the ability to “lift” values into the functor. It should satisfy the following law:
return . f ≡ fmap f . return
In addition, the join function characterizes monads:
join . fmap join ≡ join . join
join . fmap return ≡ join . return = id
join . fmap (fmap f) ≡ fmap f . join
Hope that helps.
As a few people have commented, you've found a really cute property about monads here. For reference, let's look at the signature for bind:
:: Monad m => m a -> (a -> m b) -> m b
In your case, the type a === m b as you have a [[a]] or m (m a). So, if you rewrite the signature of the above bind operation, you get:
:: Monad m => m (m b) -> ((m b) -> m b) -> m b
I mentioned that this is cute, because by extension, this works for any nested monad. e.g.
:: [[b]] -> ([b] -> [b]) -> [b]
:: Maybe (Maybe b) -> (Maybe b -> Maybe b) -> Maybe b
:: Reader (Reader b) -> (Reader b -> Reader b) -> Reader b
If you look at the function that get's applied here, you'll see that it's the identity function (e.g. id, same, :: forall a. a -> a).
This is included in the standard libraries for Haskell, as join. You can look at the source here on hackage. You'll see it's implemented as bind id, or \mma -> mma >>= id, or (=<<) id
As you say m is []. Then a is [Integer] (ignoring the fact that numbers are polymorphic for simplicity's sake) and b is Integer. So a -> m b becomes [Integer] -> [Integer].
First: we should use the standard version of same, it is called id.
Now, let's rename some type variables
id :: (a'' ~ a) => a -> a''
What this means is: the signature of id is that of a function mapping between two types, with the extra constraint that both types be equal. That's all – we do not require any particular properties, like “being flat”.
Why the hell would I write it this way? Well, if we also rename some of the variables in the bind signature...
(>>=) :: (Monad m, a'~m a, a''~m b) => a' -> (a -> a'') -> a''
...then it is obvious how we can plug the id, as the type variables have already been named accordingly. The type-equality constraint a''~a from id is simply taken to the compound's signature, i.e.
(>>=id) :: (Monad m, a'~m a, a''~m b, a''~a) => a' -> a''
or, simplifying that,
(>>=id) :: (Monad m, a'~m a, m b~a) => a' -> m b
(>>=id) :: (Monad m, a'~m (m b)) => a' -> m b
(>>=id) :: (Monad m) => m (m b) -> m b
So what this does is, it flattens a nested monad to a single application of that same monad. Quite simple, and as a matter of fact this is one the “more fundamental” operation: mathematicians don't define the bind operator, they instead define two morphisms η :: a -> m a (we know that, it's return) and μ :: m (m a) -> m a – yup, that's the one you've just discovered. In Haskell, it's called join.
The monad here is [a] and the example is pointlessly complicated. This’ll be clearer:
Prelude> [[1]] >>= id
[1]
just as
Prelude> [[1]] >>= const [2]
[2]
i.e. >>= is concatMap and is concat when used with id.
I was reviewing some code and came across the following gem, which I'd wager is a copy-paste of pointfree output:
(I thought the following would more appropriate than the usual foo/bar for this particular question :P)
import Control.Monad (liftM2)
data Battleship = Battleship { x :: Int
, y :: Int
} deriving Show
placeBattleship :: Int -> Int -> Battleship
placeBattleship x' y' = Battleship { x = x', y = y' }
coordinates :: Battleship -> (Int, Int)
coordinates = liftM2 (,) x y
Would someone be kind enough to explain the steps needed to simplify from: (i) coordinates b = (x b, y b) to: (ii) coordinates = liftM2 (,) x y? In particular, I'm a bit confused as to the use of liftM2 as I wasn't even aware that a monad was lurking in the background.
I know that (i) can also be represented as: coordinates s = (,) (x s) (y s) but I'm not sure where/how to proceed.
P.S. The following is why I suspect it's from pointfree (output is from GHCI and :pl is aliased to pointfree):
λ: :pl coordinates s = (x s, y s)
coordinates = liftM2 (,) x y
This takes advantage of the Monad instance for (->) r, also called the "reader monad". This is the monad of functions from a specific type to a. (Take a look here for motivation on why it exists in the first place.)
To see how it works for various functions, replace m with (r -> in m a. For example, if we just do liftM, we get:
liftM :: (a -> b) -> (m a -> m b)
liftM :: (a -> b) -> ((r -> a) -> (r -> b))
:: (a -> b) -> (r -> a) -> (r -> b) -- simplify parentheses
...which is just function composition. Neat.
We can do the same thing for liftM2:
liftM2 :: (a -> b -> c) -> m a -> m b -> m c
liftM2 :: (a -> b -> c) -> (r -> a) -> (r -> b) -> (r -> c)
So what we see is a way to compose two one-argument functions with a two-argument function. It's a way of generalizing normal function composition to more than one argument. The idea is that we create a function that takes a single r by passing that through both of the one-argument functions, getting two arguments to pass into the two-argument function. So if we have f :: (r -> a), g :: (r -> b) and h :: (a -> b -> c), we produce:
\ r -> h (f r) (h r)
Now, how does this apply to your code? (,) is the two-argument function, and x and y are one-argument functions of the type Battleship -> Int (because that's how field accessors work). With this in mind:
liftM2 (,) x y = \ r -> (,) (x r) (y r)
= \ r -> (x r, y r)
Once you've internalized the idea of multiple function composition like this, point-free code like this becomes quite a bit more readable—no need to use the pointfree tool! In this case, I think the non-pointfree version is still better, but the pointfree one isn't terrible itself.
The monad liftM2 is working over here is the function monad (->) a. This is equivalent to the Reader monad, as you may have seen before.
Recall the definition of liftM2:
liftM2 :: Monad m => (a -> b -> r) -> m a -> m b -> m r
liftM2 f ma mb = do
a <- ma
b <- mb
return $ f a b
So now if we substitute in (,) for f, x for ma, and y for mb, we get
liftM2 (,) x y = do
a <- x
b <- y
return $ (,) a b
Since x, y :: Battleship -> Int which is equivalent to ((->) Battleship) Int, then m ~ (->) Battleship. The function monad is defined as
instance Monad ((->) a) where
return x = const x
m >>= f = \a -> f (m a) a
Essentially what the function monad does is allow you to extract the output from several functions provided they all have the same input. A more clear example might be something like
test = do
a <- (^2)
b <- (^3)
c <- (^4)
d <- show
return (a, b, c, d)
> test 2
(4, 8, 16, "2")
You could easily rewrite
data Battleship = Battleship { x :: Int
, y :: Int
} deriving Show
placeBattleship :: Int -> Int -> Battleship
placeBattleship x y = Battleship x y
coordinates :: Battleship -> (Int, Int)
coordinates (Battleship x y) = (x, y)
It isn't point-free style, but quite simple
I want to create my own monad. This is what i wrote:
data LeafConType a = LeafCon (a,Int,Int)
instance Monad (LeafConType ) where
return = LeafCon
lc#(LeafCon (t,i,n)) >>= f = if i>=n
then lc
else f (t,i,n)
But this dont work. Ghc says:
leafcon.hs:26:1:
Occurs check: cannot construct the infinite type: a = (a, Int, Int)
When generalising the type(s) for `return'
In the instance declaration for `Monad LeafConType'
leafcon.hs:27:1:
Occurs check: cannot construct the infinite type: a = (a, Int, Int)
When generalising the type(s) for `>>='
In the instance declaration for `Monad LeafConType'
Whats wrong with that?
I want to do calculations while i is lower than n. n should be constants by I don't know yet how to do this correct. It should be some mix of State and Maybe. If you have some advices feel free to share it with me:P
About return:
Prelude> :t return
return :: (Monad m) => a -> m a
So return takes an argument of type a, and returns something of type m a. In this case m is LeafConType, so LeafConType a is returned.
Now suppose that we pass True. Then a = Bool, so the return type must be LeafConType Bool. However, you define:
return = LeafCon
So, return True becomes LeafCon True. But that is not allowed, because the type definition of LeafConType states that
data LeafConType a = LeafCon (a, Int, Int)
So for LeafConType Bool the argument to LeafCon must have type (Bool, Int, Int), not just Bool. And that is what the compile error means: a cannot be the same as (a, Int, Int). You state:
I want to do calculations while i is lower than n.
This means that you will need some default values for i and n, for otherwise it will be impossible to define return. If both of them are zero by default, then you could define:
return a = LeafCon (a, 0, 0)
About (>>=):
Prelude> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
Now look at your implementation (slightly different notation, same idea):
lc#(LeafCon (t, i, n)) >>= f | i >= n = lc
| otherwise = f t
What we see here, is that lc is returned when i >= n. But lc is of type LeafConType a, while f is a function which may return a value of type LeafConType b, for any b. As a result it could be that b is not equal to a and hence these types don't match. In conclusion, you seriously have to ask yourself one question:
Can this type of computation be expressed as a monad anyway?
The functions you specified for >>= and return don't satisfy the types required by Monad:
return :: a -> LeafConType a
Given the declaration
return = LeafCon
you give the function the incompatible type
return :: (a, Int, Int) -> LeafConType a
A statement like return 42 would therefore be impossible in your monad.
I don't understand what your monad should do at all.
First take a look at simple, working monads!
instance Monad [] where
(>>=) = concatMap
return a = [a]
instance Monad Maybe where
return = Just
(Just x) >>= f = f x
Nothing >>= f = Nothing
Judging from your description of what you want your monad to do, I think you want something a bit like this:
data LeafConType a = LeafCon { runLeafCon' :: Int -> Int -> (Maybe a, Int, Int) }
runLeafCon :: Int -> Int -> LeafConType a -> Maybe a
runLeafCon i n lc = let (t, _, _) = runLeafCon' lc i n in t
getI :: LeafConType Int
getI = LeafCon $ \i n -> (Just i, i, n)
getN :: LeafConType Int
getN = LeafCon $ \i n -> (Just n, i, n)
setI :: Int -> LeafConType ()
setI i = LeafCon $ \_ n -> (Just (), i, n)
setN :: Int -> LeafConType ()
setN n = LeafCon $ \i _ -> (Just (), i, n)
instance Monad LeafConType where
return t = LeafCon $ \i n -> if (i < n)
then (Just t, i, n)
else (Nothing, i, n)
(LeafCon k) >>= f =
LeafCon $ \i n ->
let (t, i', n') = k i n
in case t of
Nothing -> (Nothing, i', n')
(Just t') -> if (i' < n')
then runLeafCon' (f t') i' n'
else (Nothing, i, n)
example :: Int -> LeafConType ((), Int)
example x = do
i <- getI
m <- setI (i + x)
return (m, i + x)
Some examples:
*Main> runLeafCon 2 10 $ example 4
Just ((),6)
*Main> runLeafCon 2 10 $ example 8
Nothing
*Main> runLeafCon 2 10 $ example 7
Just ((),9)
I threw this together pretty quickly, it's rather ugly, and I haven't checked to see whether it obeys any of the Monad laws, so use at your peril! :)