cybertextron
cybertextron

Reputation: 10961

Defining Monad Operators

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

Answers (2)

duplode
duplode

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

Nikita Volkov
Nikita Volkov

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

Related Questions