Я хочу, чтобы иметь возможность использовать cata
от recursion-schemes
пакет для списков в церковном кодировании.Катаморфизм для церковных списков
type ListC a = forall b. (a -> b -> b) -> b -> b
Для удобства я использовал тип второго ранга, но мне все равно. Не стесняйтесь добавлять newtype
, используйте GADT и т. Д., Если вы считаете, что это необходимо.
Идея кодирования Церкви широко известна и просто:
three :: a -> a -> a -> List1 a
three a b c = \cons nil -> cons a $ cons b $ cons c nil
В основном «абстрактный неопределенный» cons
и nil
используются вместо «обычных» конструкторы. Я считаю, что все можно закодировать таким образом (Maybe
, деревья и т. Д.).
Легко показать, что List1
действительно изоморфно нормальных списков:
toList :: List1 a -> [a]
toList f = f (:) []
fromList :: [a] -> List1 a
fromList l = \cons nil -> foldr cons nil l
Таким образом, ее базовый функтор является такой же, как списки, и это должно быть возможно реализовать project
для него и использовать технику из recursion-schemes
.
Но я не мог, поэтому мой вопрос: «Как это сделать?». Для обычных списков, я могу просто шаблон матч:
decons :: [a] -> ListF a [a]
decons [] = Nil
decons (x:xs) = Cons x xs
Поскольку я не шаблон матч на функции могу, я должен использовать складку деконструкцию списка. Я мог бы написать складку на основе project
для обычных списков:
decons2 :: [a] -> ListF a [a]
decons2 = foldr f Nil
where f h Nil = Cons h []
f h (Cons hh t) = Cons h $ hh : t
Однако мне не удалось адаптировать его для церковных закодированные списков:
-- decons3 :: ListC a -> ListF a (ListC a)
decons3 ff = ff f Nil
where f h Nil = Cons h $ \cons nil -> nil
f h (Cons hh t) = Cons h $ \cons nil -> cons hh (t cons nil)
cata
имеет следующую подпись:
cata :: Recursive t => (Base t a -> a) -> t -> a
Чтобы использовать его в моих списках, мне необходимо:
- Чтобы объявить базовый тип функтор для списка с помощью
type family instance Base (ListC a) = ListF a
- Для реализации
instance Recursive (List a) where project = ...
я не на обоих этапах.
Какая у вас горелка? Я пробовал это (добавив 'newtype' для удобства), и он отлично работает. – MigMit
Я обновил свой вопрос – nponeccop
«newtype» оказался важным, а не просто удобством. Код работает сейчас. – nponeccop