If I compose two fmaps
Prelude> :t (fmap.fmap)
(fmap.fmap)
:: (Functor f, Functor f1) => (a -> b) -> f1 (f a) -> f1 (f b)
I get a function which applies a function to a value inside 2 nested leves of structure, f1 and f.
And I can use it—this works as I expected:
Prelude> (fmap.fmap) (+1) [[1,2]]
[[2,3]]
With inferred type as I expected (2 leves of structure around result)
Prelude> :t (fmap.fmap) (+1) [[1,2]]
(fmap.fmap) (+1) [[1,2]] :: Num b => [[b]]
The following does not work. I also expect this (because we can't apply sum to a single number):
Prelude> (fmap.fmap) sum [[1,2]]
<interactive>:39:2: error:
• Could not deduce (Num (t0 b))
from the context: (Num (t b), Num b, Foldable t)
bound by the inferred type for ‘it’:
(Num (t b), Num b, Foldable t) => [[b]]
at <interactive>:39:2-24
The type variable ‘t0’ is ambiguous
• In the ambiguity check for the inferred type for ‘it’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the inferred type
it :: forall (t :: * -> *) b.
(Num (t b), Num b, Foldable t) =>
[[b]]
Prelude> :t (fmap.fmap) sum [[1,2]]
(fmap.fmap) sum [[1,2]] :: (Num (t b), Num b, Foldable t) => [[b]]
BUT! If I change one level of structure to a Maybe type:
Prelude> (fmap.fmap) sum Just [1,2]
Just 3
then it begins to work, but in my opinion breaking the type signature
(fmap.fmap) :: (Functor f, Functor f1) => (a -> b) -> f1 (f a) -> f1 (f b)
(because it applies the sum function inside the first level of structure, not the second as I expected).
I think problem in my undersanding how function application order evaluates here, because I find that with parentheses this works as expected inside two levels of structure with foldable list values (vs numbers in first exapmles):
Prelude> (fmap.fmap) sum (Just [[1,2],[2,3]])
Just [3,5]
But what happens here:
Prelude> (fmap.fmap) sum Just [1,2]
Just 3
Why is the first level of stucture skipped?
What is the order of function applications here?
How does Haskell infer the final type?
Prelude> :t (fmap.fmap) sum Just [1,2] (fmap.fmap) sum Just [1,2] :: Num t => Maybe t
Why Maybe t and not Maybe List t as I understand (fmap.fmap) must determine f1 (f b) two levels of structure not one?