3

我需要一个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获得最后一个索引元素?tabulatef

4

2 回答 2

3

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)
于 2018-08-12T22:34:28.737 回答
1

您可以假设并使用Bounded (Rep f)and Enum (Rep f),即转换Rep fIntwith ,通过一些使用and on (或假设)对应物的算术toEnum更改索引,最后从back 转换为with 。IntIntminBoundmaxBoundRep ffromEnum minBound == 0IntRep ffromEnum

于 2018-08-12T21:32:07.537 回答