hl1020
hl1020

Reputation: 529

Tow definition of function "return" in monad transformer MaybeT

MaybeT is defined as

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

And, MaybeT m is also an instance of the Monad class, the function return is defined like

return  = MaybeT . return . Just

But I read that "It would also have been possible (though arguably less readable) to write return = MaybeT . return . return", this confused me.

How does return = MaybeT . return . return equals to return = MaybeT . return . Just ?

Upvotes: 2

Views: 194

Answers (2)

user2556165
user2556165

Reputation:

Consider MaybeT's definition:

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

First return definition (read it from down to up):

return =
  MaybeT .   -- put `m (Maybe a)` into `MaybeT`: MaybeT (m (Maybe a))
    return . -- put `Maybe a` into external monad: m (Maybe a)
      Just   -- put value into `Maybe`: Maybe a

Maybe is a monad too. It's return is a Just. That's why second MaybeT's return defines exactly the same function:

return =
  MaybeT .   -- put `m (Maybe a)` into `MaybeT`: MaybeT (m (Maybe a))
    return . -- put `Maybe a` into external monad: m (Maybe a)
      return -- it's the same as `Just` for `Maybe`: Maybe a

Upvotes: 7

J. Abrahamson
J. Abrahamson

Reputation: 74354

In Haskell functions like return are polymorphic. If you examine the type of return you'll see that it's return :: Monad m => a -> m a which indicates that it works for any monad. As it turns out, Maybe is a monad and so there must be (somewhere in the standard libraries) an instance declaration like

instance Monad Maybe where
  return = ...
  ...

and, as it turns out, the instance definition of return for Maybe is

instance Monad Maybe where
  return = Just

So that indicates why we are allowed to replace return with Just, but it doesn't explain why Haskell actually does it.

It turns out that Haskell uses type inference to decide what the "actual" type of a polymorphic function is. So, to be clear, what's happening in your example is that Haskell is able to recognize that the rightmost return must return a value wrapped in Maybe and thus knows to specialize return to return :: a -> Maybe a and then it uses the instance Monad Maybe definition for return and turns it into Just.

Upvotes: 5

Related Questions