Прошлым летом я рассмотрел понятие складывания последовательности, выровненной по типу, asking here, как можно реализовать аналог foldr
в терминах аналога foldMap
. Иоахим Брейтнер смог сделать это с помощью сложного нового стиля. Теперь я решил подумать о понятии , пересекающем последовательность, выровненную по типу. Первая мысль, я был простой переводКак перемещаться по последовательностям, выровненным по типу?
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
в Foldable
заменяется на Category
для TAFoldable
, тем Applicative
из Traversable
должен быть заменен чем-то сильнее. Я придумал следующее, основанное на индексированных аппликативных функциях, разработанных в стиле Atkey, но он чувствует себя немного неудобно, тем более, что индексы, похоже, хотят вернуться назад. В принципе, я просто бросил типы на стену, пока некоторые из них не застряли. Есть ли еще более принципиальный/понятный подход?
{-# 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
Вводится понятие mappability для последовательностей типа выровнен, на основе метода в type-aligned
:
class TAMappable t where
tmap :: (forall x y . c x y -> d x y)
-> t c p q -> t d p q
Мое понятие foldability для последовательностей типа выровненных:
class TAFoldable f where
tfoldMap :: Category d
=> (forall x y . c x y -> d x y)
-> f c p q -> d p q
Мой лучший так далеко понятие traversability для последовательностей типа выровненных:
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)
Доказательство того, что по крайней мере, самый простой последовательности типа выровнен допускает (несколько странно) 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
Я думаю, что я нашел намек на источник backwardsness. Мой список, выровненный по строкам, начинается с конца цепи композиции, что заставляет его бороться с порядком индекса IxApplicative
.Одним из вариантов является заменить определение TAL
выше
data TAL :: (k -> k -> *) -> k -> k -> * where
Nil :: TAL c x x
(:::) :: c x y -> TAL c y z -> TAL c x z
, что делает очевидную работу экземпляра:
instance TATraversable TAL where
ttraverse _ Nil = ireturn Nil
ttraverse f (x ::: xs) = imap (:::) (f x) `iap` ttraverse f xs
Но это вроде противный смотреть, если честно.
Я думаю, что я * начало *, чтобы понять backwardsness: мое представление о последовательности типа выровненных начинается на * конец * из составной цепи и движется к * началу *. Это (я думаю?) Делает аппликаторы индекса неудобными. Но это делает другие вещи красивее. Хммм. – dfeuer
Почему второй «TAL» yucky? Это определение [здесь] (https://hackage.haskell.org/package/type-aligned-0.9.6/docs/Data-TASequence-ConsList.html) и [здесь] (https://github.com/ agda/agda-stdlib/blob/master/src/Data/Star.agda) тоже. –
@ András Kovács, это не изначально плохо, но это означает, что складывая список, вы должны заменить каждый 'Cons' на' >>> ', а не' .'. Я не уверен, какой стиль в конечном итоге станет более удобным. – dfeuer