Обновление n-арного продукта из sop-core с совместимой суммой - PullRequest
1 голос
/ 26 октября 2019

Я работаю с библиотекой sop-core и хочу написать функцию следующего типа:

patch :: NS I xs -> NP Maybe xs -> NP Maybe xs

xs - это список уровня типатаких типов, как '[Int,Char,Bool]. I - функтор тождеств. NS I xs является типом n-арной суммы. NP Maybe xs - это n-арный продукт, в котором каждый компонент может существовать или не существовать.

patch должен взять значение из n-арной суммы и заполнить соответствующий слотn-ary продукт, перезаписывает его, если он уже существует. Например:

patched :: NP Maybe '[Int,Char,Bool]
patched = patch (Z (I 3)) (Nothing :* Nothing :* Nothing :* Nil)
-- patched == Just 3 :* Nothing :* Nothing :* Nil

Я подозреваю, что решение может включать функцию injections, но я в замешательстве.

1 Ответ

1 голос
/ 27 октября 2019

В конце концов, для решения не требуется injections, а функция expand_NS, которая преобразует сумму в продукт, заполняя несовпадающие компоненты продуктазначение по умолчанию.

Хитрость в том, чтобы создать произведение из сеттеров , которое мы можем применить к исходной записи, используя liftA2_NP. Когда мы расширяем сумму, несовпадающие компоненты заполняются тождественной функцией. Но мы перезаписываем соответствующий компонент значением в сумме.

Сначала нам понадобится вспомогательный тип

newtype Mendo a = Mendo { getMendo :: Maybe a -> Maybe a }

, а код для patch будет:

patch :: forall xs. SListI xs => NS I xs -> NP Maybe xs -> NP Maybe xs
patch piece =
  let mendos :: NP Mendo xs -- product of setters
      mendos = expand_NS (Mendo id) (liftA_NS (\(I x) -> Mendo (\_ -> Just x)) piece)
   in liftA2_NP (\(Mendo f) x -> f x) mendos
...