What is Representable used for in Haskell?

前端 未结 1 633
被撕碎了的回忆
被撕碎了的回忆 2021-02-19 22:24

I am looking to understand what does Representable stand for in Haskell. The definition

Representable endofunctors over the category of Haskell types are

1条回答
  •  终归单人心
    2021-02-19 22:55

    Representables are containter-like functors that have a "special relationship" with another type that serves as an index into the Representable. In the Haskell definition, this index type is given by the associated type family type Rep f :: *

    For every value of the index and for every value of the Representable, we can call the index :: f a -> Rep f -> a function to get the corresponding element. And tabulate :: (Rep f -> a) -> f a constructs a container where each element is derived from its own index.

    Now, here is an example of a functor that is NOT representable: the typical Haskell list type []. One might naively think that it can be indexed by something like a Natural, but the problem is that lists can be empty, or not have enough elements to reach a given index.

    An always-infinite type like data Stream a = Stream a (Stream a) is Representable and it's indexed by Natural, because there will always be a value for any given Natural that we pass to index.

    Similarly, the homogeneous pair data Pair a = Pair a a is indexed by the type Bool: the index tells us which of the components to select.

    If we get dependent-ish, fixed-size vectors are Representable and are indexed by finite naturals bounded by the size of the vector. They aren't indexed by unbounded Naturals because then we could have an out-of-bounds access!


    Reading the various instances defined for Representable is instructive, but it seems we have to get down to the source code because the associated types are not visible in the Haddocks. Some interesting tidbits:

    • The Identity functor is indexed by the unit type (), this makes sense because Identity only has one "slot" so to speak, so we don't need to provide any information.

    • The "functions from some type" type ((->) e) is indexed by the source type itself. And index is simply id. This is what's meant by "isomorphic to the reader monad", because the Reader e monad is just a newtype over ((->) e).

    • The Composition (nesting) of two representable functors is again Representable, and it is indexed by the pair of the original indexes! This makes sense: first we must know how to index into the outer functor, and then into the inner one.

    • The Product (pairing) of two Representable functors is indexed by the sum (Either) of the original indexes. The branch of the Either tells us in which part of the product to index.

    • A notable omission (because it is not true in general): there is no (Representable f, Representable g) => Representable (Sum f g) instance.

    0 讨论(0)
提交回复
热议问题