Representable
一般不支持reverse
,因为无限的固定形状结构是可表示但不可逆的,例如流:
{-# 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
对于通用反转,您需要Rep
像 Conal 的回答中那样有限,但我认为要求Traversable
本身是可以接受的,并且可能比大多数情况下更index
有效tabulate
。您可以使用应用程序反转State
:
import Control.Monad.State.Strict
reverseT :: Traversable t => t a -> t a
reverseT ta =
evalState (traverse (\_ -> gets head <* modify tail) ta)
(foldl (flip (:)) [] ta)