Haskell 如何在不使用列表的情况下编写reverseT?
我需要一个Haskell 如何在不使用列表的情况下编写reverseT?,haskell,reverse,foldable,representable,Haskell,Reverse,Foldable,Representable,我需要一个reverseT的替代方案,它不使用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 -> ?
reverseT
的替代方案,它不使用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
,以便在构建f
时获得tablete
提供的最后一个索引元素吗?您可以假设并使用有界(Rep f)
和枚举(Rep f)
,即用toEnum
将Rep f
转换为Int
,通过使用minBound
和maxBound
的Rep f
上的Int
算法更改索引(或假设fromnum minBound==0
),最后,从Int
返回到Rep f
,使用fromnum
Representable
通常不支持反向
,因为无限固定形状结构是可表示的,但不可逆的,例如。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
使用,您可以对任何
可遍历的t
进行覆盖(部分遍历)反向::可遍历的t=>t~>t
。Traversable
约束还确保我们保持了t
的形状。额外的挑战:使用不同的函子不使用部分函数。谢谢!您的解决方案看起来像是作为中间状态通过列表。不是这样吗?@dbanas是的。使用可遍历的解决方案,您不会做得更好。@dfeuer解决方案带来额外的挑战。很好!我怀疑你真的需要这种温和的恶作剧(插件或不安全的)来提高效率,但以某种方式避免它们会更酷。
import Control.Monad.State.Strict
reverseT :: Traversable t => t a -> t a
reverseT ta =
evalState (traverse (\_ -> gets head <* modify tail) ta)
(foldl (flip (:)) [] ta)