Representable
does not support reverse
in general, because infinite fixed-shape structures are representable but not reversible, e. g. streams:
{-# language DeriveFunctor, TypeFamilies #-}
import Data.Distributive
import Data.Functor.Rep
data Stream a = Cons {hd :: a, tl :: Stream a} deriving Functor
instance Distributive Stream where
distribute fa = Cons (hd <$> fa) (distribute (tl <$> fa))
data Nat = Z | S Nat
instance Representable Stream where
type Rep Stream = Nat
tabulate f = Cons (f Z) (tabulate (f . S))
index as Z = hd as
index as (S n) = index (tl as) n
For generic reversal you need finite Rep
as in Conal's answer, but I think requiring Traversable
by itself would be acceptable and probably more efficient than index
and tabulate
in most cases. You can reverse using the State
applicative:
import Control.Monad.State.Strict
reverseT :: Traversable t => t a -> t a
reverseT ta =
evalState (traverse (\_ -> gets head <* modify tail) ta)
(foldl (flip (:)) [] ta)