I am trying to understand Constant Functor from the https://en.wikipedia.org/wiki/Functor website and can not imaging visually.
It would be also good, if someone can show it as a haskell code, what a Constant Functor is and for what is good for.
I am trying to understand Constant Functor from the https://en.wikipedia.org/wiki/Functor website and can not imaging visually.
It would be also good, if someone can show it as a haskell code, what a Constant Functor is and for what is good for.
A constant functor is a functor whose object function is a constant function. In haskell:
newtype Const r a = Const { unConst :: r }
instance Functor (Const r) where
fmap _ (Const r) = Const r
It maps every type a
to r
in a sense, and every function of type a -> b
to the identity function on r
It is good for similar things that the const
function is good for! Passing to higher order functions, etc.
One interesting use case is in the definition of lens based getters.
Like with constant functions: a constant functor is any functor that “ignores” its parameter, and furthermore has a trivial fmap
operation.
In Haskell, what this means is that every value F a
contains only data that doesn't contain a
in any way. I.e., it's just some other fixed type, say R
. Clearly, this could be any type, so the actual standard Const
functor has this as another parameter:
newtype Const r x = Const { getConst :: r }
This is a (Hask-endo-)functor because it maps any type x
to another type Const r x
– which is actually isomorphic to just r
. And fmap
ping, which should change only the x
values within the Const r x
structure... well, there are none, so nothing is changed.
instance Functor (Const r) where
fmap _ (Const r) = Const r
From Data.Functor.Const
:
newtype Const a b = Const { getConst :: a } deriving Show
Const a b
is a type that holds a value of type a
, but "tagged" with type b
as well. Given that Const
has type Type -> Type -> Type
, it itself is not a functor, but Const a
is for any given type a
.
instance Functor (Const m) where
fmap _ (Const v) = Const v
No matter what function you apply, it is ignored and the original value is returned, though with a (possibly) new type.
As an example, let's create a value involving a Char
. The argument sets the first type, leaving the second type unconstrained.
> v = Const 'c'
> v
Const {getConst = 'c'}
> :t v
v :: Const Char b
Mapping a function over v
constrains the second type to be the return value of that function.
> fmap (+1) v
Const {getConst = 'c'}
> :t fmap (+1) v
fmap (+1) v :: Num b => Const Char b
Mapping a different function works the same, but constrains the second type in a different way, again consistent with the return value of the function.
> fmap (++"foo") v
Const {getConst = 'c'}
> :t fmap (++"foo") v
fmap (++"foo") v :: Const Char [Char]