Jimmy Hu
Jimmy Hu

Reputation: 121

Why does `fmap sum Just` typecheck?

We know fmap is fmap :: Functor f => (a -> b) -> f a -> f b and sum is sum :: (Num a, Foldable t) => t a -> a, but the code below confuse me.

> :t (fmap sum Just)
(fmap sum Just) :: Num b => b -> b
> fmap sum Just 3
3

why?

Upvotes: 11

Views: 191

Answers (1)

Adam Wagner
Adam Wagner

Reputation: 16127

I think there are probably two confusing bits here.

The first, most obvious, is that sum works on Foldable things, not just lists. Therefore:

sum (Just 3) == 3

The second is the functor instance you are using. Since Just is a function, as that is the second argument to fmap, you are using the reader instance of fmap, which is defined here (https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#line-638) as simply (.).

It looks weird, and like it shouldn't type-check, because you are supplying three arguments to fmap, but actually, the result of the (fmap sum Just) is a function:

Prelude> :t fmap sum Just
fmap sum Just :: Num b => b -> b  

If we replace fmap with ., things start to make a little more sense.

Prelude> (.) sum Just 3
3

Prelude> (sum . Just) 3
3

Which is the same as

sum (Just 3)

Upvotes: 12

Related Questions