我需要不使用reverseT
的{{1}}替代方案。
显然,这段代码是不正确的,但是证明了我追求的想法:
toList
有人知道我可以用什么来代替reverseF
:: (Foldable f, Representable f, Num (Rep f))
=> f a -> f a
reverseF f = tabulate $ \ix -> index f $ last - ix
where last = length f - 1 -- Incorrect; length -> ?
,以便在构建length
时获得tabulate
提供的最后一个索引元素吗?
答案 0 :(得分:3)
Representable
通常不支持reverse
,因为无限固定形状的结构可以表示但不可逆,例如。 G。流:
{-# 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
对于一般逆转,您需要像Conal的答案中那样有限的Rep
,但是我认为单独要求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)
答案 1 :(得分:1)
您可以假设并使用Bounded (Rep f)
和Enum (Rep f)
,即用Rep f
将Int
转换为toEnum
,将索引更改Int
在Int
上使用minBound
和maxBound
的{{1}}对应项(或假设Rep f
),最后从fromEnum minBound == 0
返回到{{1 }}和Int
。