Let's take fmap . const
fmap . const
as a simple example where I try to understand what it does:
fmap :: Functor f => (a -> b) -> f a -> f b
const :: a -> b -> a
The fist thing I notice is that a
, b
are ambiguous when I try to understand fmap . const
fmap . const
. The use of two or more related signatures together is what I mean by " GHCI
session".
Here's example of what would help me understand things better:
fmap :: Functor f => (a -> b) -> f a -> f b
const :: c -> d -> c
fmap . const :: Functor g => h -> g i -> g h
Let's bind g = f
and reduce g
:
fmap . const :: Functor f => h -> f i -> f h
Pick h :: h
as a least-confusing variable name for the pointful version:
\h -> fmap (const h) :: Functor f => h -> f i -> f h
Let's bind h = c
and reduce h
:
\c -> fmap (const c) :: Functor f => c -> f i -> f c
Now, it is much easier to see that c
in fc
came from first argument to const
. I also see that i
and a
are free since I did not need to "operate" on them.
Questions:
GHCI
session? GHCI
session? The type variables in signatures are actually bound by an implicit universal quantifier. There is a language extension to make it explicit, check that this compiles :
{-# LANGUAGE ExplicitForAll #-}
fmapPrime :: forall a b f. Functor f => (a -> b) -> f a -> f b
fmapPrime = fmap
constPrime :: forall a b. a -> b -> a
constPrime = const
fmapConst :: forall a b f. Functor f => b -> f a -> f b
fmapConst = fmap . const
So you cannot say that the type variables variables are "reused" : they are not free.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.