我应该如何遍历类型对齐的序列?

时间:2016-02-01 06:03:20

标签: haskell applicative gadt

去年夏天,我考虑了折叠类型对齐序列的概念,asking here如何根据foldr的类似物实现foldMap的类似物。 Joachim Breitner能够借助一个棘手的新类型来做到这一点。现在我决定考虑遍历类型对齐序列的概念。我的第一个想法是简单的翻译

class TATraversable t where
  ttraverse :: Applicative f
            => (forall x y . c x y -> f (d x y))
            -> t c p q -> f (t d p q)

mapMThrist包中的thrist基本相同。不幸的是,这似乎不足以实现

tfoldMap :: Category d
         => (forall x y . c x y -> d x y)
         -> f c p q -> d p q

由于Monoid的{​​{1}}被Foldable替换为CategoryTAFoldable的{​​{1}}必须被某些内容替换更强。我想出了以下基于Atkey风格的索引应用程序,但感觉有点尴尬,特别是因为索引似乎最终倒退了。基本上,我只是在墙上扔了类型,直到其中一些卡住了。是否有一些更有原则性/可理解的方法?

Applicative

索引的Atkey风格仿函数的多边形版本。我实际上并不需要任何代码的多重性,但我认为任何人实际上使用它会期望它适用于所有类型的幻像。此外,这给了我一个很好的借口来复制这里的定义供参考:

Traversable

基于{-# LANGUAGE ScopedTypeVariables, RankNTypes, GADTs, PolyKinds #-} module ITrav where --Not using this because it's not polykinded --import Data.Functor.Indexed import Control.Category import Prelude hiding (id, (.)) 中的方法的类型对齐序列的可映射性概念:

class IxFunctor f where
  imap :: (a -> b) -> f j k a -> f j k b

class IxFunctor m => IxPointed m where
  ireturn :: a -> m i i a

class IxPointed m => IxApplicative m where
  iap :: m i j (a -> b) -> m j k a -> m i k b

我对类型对齐序列的可折叠性概念:

type-aligned

我对类型对齐序列的可穿越性的最佳概念:

class TAMappable t where
  tmap :: (forall x y . c x y -> d x y)
       -> t c p q -> t d p q

通过遍历绘制机器:

class TAFoldable f where
  tfoldMap :: Category d
           => (forall x y . c x y -> d x y)
           -> f c p q -> d p q

通过遍历折叠的机器:

class (TAMappable t, TAFoldable t) => TATraversable t where
  ttraverse :: IxApplicative m
            => (forall x y . c x y -> m x y (d x y))
            -> t c p q -> m p q (t d p q)

证明至少最简单的类型对齐序列允许(有点奇怪)newtype Identity2 x y z = Identity2 {runIdentity2 :: z} instance IxFunctor Identity2 where imap f (Identity2 x) = Identity2 (f x) instance IxPointed Identity2 where ireturn = Identity2 instance IxApplicative Identity2 where iap (Identity2 f) (Identity2 x) = Identity2 (f x) tmapDefault :: TATraversable t => (forall x y . c x y -> d x y) -> t c p q -> t d p q tmapDefault f = runIdentity2 . ttraverse (Identity2 . f) 实例。

newtype Consty d x y z = Consty { getConsty :: d x y }
instance IxFunctor (Consty d) where
  imap _ (Consty x) = Consty x
instance Category d => IxPointed (Consty d) where
  ireturn _ = Consty id
instance Category d => IxApplicative (Consty d) where
  iap (Consty x) (Consty y) = Consty (y . x)

tfoldMapDefault :: (Category d, TATraversable t) => (forall x y . c x y -> d x y) -> t c p q -> d p q
tfoldMapDefault f = getConsty . ttraverse (Consty . f)

我想我已经找到了一个暗示来源的暗示。我的类型对齐列表以组合链的 end 开头,这使得它与TATraversable索引顺序对抗。一种选择是用

替换上面infixr 5 ::: data TAL :: (k -> k -> *) -> k -> k -> * where Nil :: TAL c x x (:::) :: c y z -> TAL c x y -> TAL c x z instance TAMappable TAL where tmap = tmapDefault instance TAFoldable TAL where tfoldMap = tfoldMapDefault instance TATraversable TAL where ttraverse _ Nil = ireturn Nil ttraverse f (x ::: xs) = imap (flip (:::)) (ttraverse f xs) `iap` f x 的定义
IxApplicative

这使得明显的实例工作:

TAL
但是,说实话,这有点令人讨厌。

1 个答案:

答案 0 :(得分:2)

我只想出了一种方法:交换ttraverse定义中的类型索引:

class (TAMappable t, TAFoldable t) => TATraversable t where
  ttraverse :: IxApplicative m
            => (forall x y . c x y -> m y x (d x y))
            -> t c p q -> m q p (t d p q)

newtype Consty d y x z = Consty { getConsty :: d x y }
instance Category d => IxApplicative (Consty d) where
  iap (Consty x) (Consty y) = Consty (x . y)

然后事情就像我原本希望的那样。不过,我不知道这是不是一个好主意。

幸运的是,似乎无论我采用哪种方式,我都可以使用类似Control.Applicative.Backwards.Backwards的方式进行反转!

newtype IxBackwards m i j a = IxBackwards {ixForwards :: m j i a}

instance IxFunctor f => IxFunctor (IxBackwards f) where
  imap f (IxBackwards x) = IxBackwards (imap f x)

instance IxPointed f => IxPointed (IxBackwards f) where
  ireturn = IxBackwards . ireturn

instance IxApplicative f => IxApplicative (IxBackwards f) where
  iap (IxBackwards fs) (IxBackwards xs) =
    IxBackwards $ imap (flip ($)) xs `iap` fs

ttraverse类型签名中索引的顺序似乎决定了遍历顺序。如果我不是很困惑,遍历IxBackwards会颠倒那个顺序:

traverseOpposite :: (IxApplicative m, TATraversable t) => (forall x y . c x y -> m x y (d x y)) -> t c p q -> m p q (t d p q)
traverseOpposite f  = ixForwards . ttraverse (IxBackwards . f)