5

Is Haskell's pure function the same as return?

I just can make a type an instance of Monad if it is already an instance of Applicative, right? So I wonder that Applicative's pure is everytime interchangeable with Monad's return? Is there an example where they are not the same?

data HelloType a = HelloType { getValue :: a } deriving (Show, Eq)

instance Functor HelloType where
    fmap f (HelloType y) = HelloType (f y)

instance Applicative HelloType where
    (<*>) (HelloType f) (HelloType x) = HelloType (f x)
    pure = HelloType

instance Monad HelloType where
    (>>=) (HelloType x) f = f x
    -- return = pure
    return = HelloType

plus3 :: (Num a) => Maybe a -> HelloType (Maybe a)
plus3 (Just x) = HelloType (Just $ x + 3)
plus3 Nothing = HelloType Nothing

main= do
    let withPure = pure (Just 3) >>= plus3 >>= plus3
        withReturn = return (Just 3) >>= plus3 >>= plus3
    print $ withPure == withReturn -- TRUE
  • 5
    Every type that is an instance of `Monad` must have its `return` equal to `pure`. But there are types which are `Applicative` but not a `Monad`, and therefore have a `pure` but no `return`. `ZipList` is the traditional example here. – Robin Zigmond Feb 18 '19 at 15:49
  • @RobinZigmond Thank you for this fast reply! Is it unconventional to just use pure in larger Haskell projects? So to never define return for Monad instances? If you would like to add your first comment as an answer, I can mark this question as resolved. – christian wuensche Feb 18 '19 at 15:58
  • unfortunately I'm pretty new to Haskell, so I can't speak for what people do in "larger Haskell projects". (Although I'm sure some of the other regular contributors here can help you on this.) Personally I like to use `return` if I'm working in the context of a `Monad` (for example, a `do` block) but just use `pure` if I happen to need the function "on the fly" (to embed an element in a singleton list, typically). But I don't really know what the idiomatic way is to use them. – Robin Zigmond Feb 18 '19 at 16:03
  • 3
    @chrisheyn As far as I can see, using `pure` everywhere would be fine. Many haskellers still use `return`, especially in `do` blocks, both because of habit (`pure` is more recent) and because they want to remark we are working with a monad. Some instead tend to use `pure`, even when `return` would also work. It's hard to say which one is more idiomatic, but I'd say that using `pure` everywhere would generally be regarded as a matter of "personal style". – chi Feb 18 '19 at 16:42
  • Thank you @chi. I can imagine that using `return` adds more information to the code. That's sounds like a good approach when working with Monads. – christian wuensche Feb 18 '19 at 16:46
  • 3
    My personal opinion (& speculation) is that, in a parallel universe where `Applicative` was introduced in the base library at the same time as `Monad`, we would not have `return` at all, since that would be redundant. That reasoning could justify a position stating "let's pretend we did the right thing from day one, and consequently behave as if `return` did not exist". Feel free to use `pure` in your code as you wish. As long as you don't become too dogmatic about it, you'll be fine :) – chi Feb 18 '19 at 16:58

1 Answers1

9

Every type that is an instance of Monad must have its return equal to pure.

In particular, since Applicative was made a superclass of Monad, return doesn't need to be defined because by default it is defined to be a synonym of pure: see the definition:

Furthermore, the Monad and Applicative operations should relate as follows:

  • pure = return

Minimal complete definition

(>>=)

Notice that the minimal definition only requires >>=, not return, and the requirement that pure = return (which, like all such "laws", cannot be enforced by the language but must hold for all "sane" implementations, otherwise the semantics will not be correct).

But there are types which are Applicative but not a Monad, and therefore have a pure but no return. ZipList is the traditional example.

Robin Zigmond
  • 17,805
  • 2
  • 23
  • 34