Why does `fmap sum Just` typecheck?
Asked Answered
L

1

11

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?

Livable answered 10/4, 2017 at 3:46 Comment(2)
I'm sure, you can try it.Livable
Yep, I realised sum comes from Data.FoldableMarivelmariya
M
12

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)
Mindamindanao answered 10/4, 2017 at 4:1 Comment(2)
Thank you so much. I'm haskell newbie. I haven't learned reader instance, but I think you're right. I will check it later.Livable
You're welcome. This instance usually shows up as ((->) r) in most cases, and it can be easy to miss what's going on when this shows up somewhere, simply because functions feel like they should act somehow special, but in Haskell it's a type like everything else so it's much more consistent than other languages.Mindamindanao

© 2022 - 2024 — McMap. All rights reserved.