Reputation: 10961
In Haskell's Monads, I can easily define the operator (>=>)
as :
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
f >=> g = \x -> f x >>= g
I also know that (>>=)
can be expressed using (>=>)
: Let's call (>>=)
as (..)
:
(..) :: Monad m => m a -> (a -> m b) -> m b
m .. k = m >=> \_ -> k
However something is not right ... could someone point what?
Upvotes: 1
Views: 175
Reputation: 34378
The idea of using a constant function (that is, \_ -> -- etc.
) to make a function out of the argument which isn't a function so that you can pass it to (>=>)
is sound. There are just two issues. Firstly, you are doing it to the wrong argument, as the one which isn't a function is m
:
GHCi> :t \m k -> (\_ -> m) >=> k
\m k -> (\_ -> m) >=> k :: Monad m => m b -> (b -> m c) -> a -> m c
Secondly, (>=>)
gives you a function (of type a -> m c
in the demo just above). You have to apply it to something to get a result type that matches the one of (>>=)
. As that argument is irrelevant (you are ultimately feeding it to a constant function) you can just use ()
:
GHCi> :t \m k -> ((\_ -> m) >=> k) ()
\m k -> ((\_ -> m) >=> k) () :: Monad m => m b -> (b -> m c) -> m c
And that's it. I find it slightly prettier to use the const
function rather than writing \_ ->
, and so I would write it as:
(>>..) :: Monad m => m a -> (a -> m b) -> m b
m >>.. k = (const m >=> k) ()
Upvotes: 9
Reputation: 43309
The solution is the following:
(..) :: Monad m => m a -> (a -> m b) -> m b
m .. k =
(const m >=> k) undefined
Using const
we're lifting an operation of type m a
to whatever -> m a
. This lifted version does not give a damn, what we pass to it so it might as well be the undefined
.
Upvotes: 2