Reputation: 65
While studying Haskell, I learned that <$
is defined as (<$) = fmap . const
. I wanted to understand this by deriving its type and behavior from fmap
, const
, and (.)
.
However, no matter how much I tried, I couldn't derive the expected type Functor f => b -> f a -> f b
, and when looking at fmap . const
alone (without <$
), I have no intuition about how it actually behaves.
Could someone help me understand this?
Upvotes: 1
Views: 64
Reputation: 477462
(<$) = fmap . const
can be rewritten to:
(<$) x = fmap (const x)
which is then equivalent to:
(<$) x = fmap (\y -> x)
It is thus an functor-map that ignores the value to map, and repaces it by the value the <$
has taken.
For example for a list:
1 <$ [1, 4, 2, 5]
will return:
[1, 1, 1, 1]
and for Maybe
, 42 <$ Just 73
is Just 42
, whereas for 42 <$ Nothing
, it is Nothing
.
For IO
, it thus generates an IO a
that will run the IO
actions, but repaces the "result" with a defined one, so:
42 <$ readLine
will ask for a line as value, but then return 42
alltogheter.
We can automatically derive the type by first looking at the types of the functions that are applied. (<$) = fmap . const
is equivalent to:
(<$) = (.) fmap const
with (.) :: (b -> c) -> (a -> b) -> a -> c
, fmap :: Functor f => (d -> e) -> f d -> f e
, and const :: g -> h -> g
, so we can derive the type with:
(.) :: ( b -> c ) -> (a -> b ) -> a -> c
fmap :: Functor f => (d -> e) -> f d -> f e
const :: g -> (h -> g)
so that gives us:
(.) :: ( b -> c ) -> (a -> b ) -> a -> c
fmap :: Functor f => (d -> e) -> f d -> f e
const :: g -> (h -> g)
-------------------------------------------------------------------------
b ~ d -> e
c ~ f d -> f e
a ~ g
b -> h -> g
d ~ h
g ~ e
Where x ~ y
means that x
and y
are the same type.
The result of (.) fmap const
, which thus has type a -> c
can thus be "specialized" to:
(.) fmap const :: a -> c
(.) fmap const :: Functor f => g -> (f d -> f e)
(.) fmap const :: Functor f => e -> (f d -> f e)
(.) fmap const :: Functor f => e -> (f h -> f e)
so:
(.) fmap const :: Functor f => e -> (f h -> f e)
Upvotes: 3