4

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.

softshipper
  • 32,463
  • 51
  • 192
  • 400
  • 1
    The constant functor maps every object in the source category to a single object in the destination category. It maps every morphism to the identity morphism on that single object. – Kyle Parsons Oct 25 '19 at 14:27

3 Answers3

8

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.

sara
  • 3,521
  • 14
  • 34
  • what is the `identity function on r`. I can not see it. – softshipper Oct 25 '19 at 14:47
  • 2
    The identity function is `id x = x`. What I'm referring to is the fact that `fmap f (Const r) == id (Const r) == Const r` for all possible pairs of `f` and `r` – sara Oct 25 '19 at 14:52
  • @sara Not quite; the function doesn't change the wrapped value, but it does change the type. If `f :: t1 -> t2` and `v :: Const a t1`, then `fmap f v :: Const a t2`, but `id v :: Const a t1`. – chepner Oct 25 '19 at 14:58
  • I choose to adopt the categorical view that "equal up to isomorphism" is quite close enough to equal :p – sara Oct 25 '19 at 15:12
  • Or in haskell land, equal up to safe coercion! – sara Oct 25 '19 at 15:13
  • @sara It's an important point, though, because it explains why you can't simply define `fmap _ = id`. (A question on this point [came up](https://stackoverflow.com/q/58494308/1126841) just a few days ago.) – chepner Oct 25 '19 at 17:30
4

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 fmapping, 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
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
3

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]
chepner
  • 497,756
  • 71
  • 530
  • 681