Индуктивный лифтинг - PullRequest
5 голосов
/ 12 марта 2020

Я хотел бы объединить различные лифты в один класс

class Lift a b where
  lift :: a -> b

, чтобы вместо fmap, liftA2, liftA3, * * 1003 можно было использовать lift *.

Теперь достаточно просто написать примеры для них:

instance Functor f => Lift (a -> b) (f a -> f b) where
  lift = fmap
instance Applicative f => Lift (a -> b -> c) (f a -> f b -> f c) where
  lift = liftA2
instance Applicative f => Lift (a -> b -> c -> d) (f a -> f b -> f c -> f d) where
  lift = liftA3

Однако для liftA2 и выше имеется индуктивное свойство. То есть мы можем извлечь лифт из небольших лифтов. Например:

liftA2 f a b       = (liftA  f a)       <*> b
liftA3 f a b c     = (liftA2 f a b)     <*> c
liftA4 f a b c d   = (liftA3 f a b c)   <*> d
liftA5 f a b c d e = (liftA4 f a b c d) <*> e
...

Поэтому я бы хотел вместо того, чтобы перечислять каждый лифт в качестве отдельного экземпляра, использовать индукцию для создания всех из них. Однако, хотя определение является индуктивным, у меня возникают проблемы с выражением взаимосвязи между одним подъемом и следующим алгебраически . То есть, хотя я могу описать это, это не комбинация lift s и простых комбинаторов.

Даже если я напишу их без разбора, мы увидим, что каждый уровень более сложный, чем последний:

liftA2 = ((<*>) .) . liftA
liftA3 = (((<*>) .) .) . liftA2
liftA4 = ((((<*>) .) .) .) . liftA3
liftA5 = (((((<*>) .) .) .) .) . liftA4
...

Теперь я думаю, что это можно обойти, добавив gh c natural к классу

class Lift (n :: Nat) (a :: Type) (b :: Type) | a b -> n  where
  lift :: a -> b

И затем используя вспомогательный класс типов для выполнения большого количества связующего Работа. Однако это решение было бы далеко не элегантным, и я рассматриваю его в основном как последнее средство, поскольку я бы предпочел не раздувать класс с Nat, используемым только для вычислений.

Есть ли способ, которым я индуктивно определяю lift без изменения определения класса, как это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...