Объединение списков вариантов разных типов в purescript

Я играл с Purescript как средством экспериментов с программированием на языке, подобном Haskell, с полиморфизмом строк и столбцов.

В частности, используя вариантный пакет Purescript, я пытался написать операцию для последовательного объединения двух списков "примечаний", где два списка, возможно, имеют непересекающиеся наборы вариантов. Идея здесь состоит в том, чтобы позволить пользователям иметь возможность комбинировать оценки, объявленные в некотором подмножестве заметок, для автоматического объединения с оценками, содержащими супернабор, без каких-либо явных преобразований.

Например, учитывая следующий шаблон, чтобы упростить работу с вариантами:

import Data.Variant
import Prim.Row

data A = A
data B = B
data C = C
data D = D
data E = E
data F = F
data G = G
data H = H

_A = SProxy :: SProxy "_A"
_B = SProxy :: SProxy "_B"
_C = SProxy :: SProxy "_C"
_D = SProxy :: SProxy "_D"
_E =  SProxy :: SProxy "_E"
_F =  SProxy :: SProxy "_F"
_G =  SProxy :: SProxy "_G"

Я могу определить следующие типы:

type CNatural = Variant (
    _A :: A,  
    _B :: B,
    _C :: C,
    _D :: D,
    _E :: E,
    _F :: F,
    _G :: G)
  
type CPentatonic = Variant (
    _A :: A,  
    _C :: C,
    _D :: D,
    _E :: E,
    _G :: G)

Учитывая это, я могу определить две оценки:

score1 :: Array CPentatonic  
score1 = [inj _A A,inj _C C]

score2 :: Array CNatural
score2 = [inj _C C, inj _B B]

Итак, чтобы объединить их, мне нужна функция подписи

combine :: forall v w u. Union w v u => 
     Array (Variant v)
  -> Array (Variant w)
  -> Array (Variant u)

Однако моя попытка:

combine x y = (map expand x) <> (map expand y)

дает

  No type class instance was found for

    Prim.Row.Union v2
                   t3
                   u4

  The instance head contains unknown type variables. Consider adding a type annotation.

Если я попробую изменить Union v w u ограничение на Union w v u ограничение, ошибка переходит туда и обратно между первыми map expand, а второй map expand, но ничего из того, что я делаю, похоже, не разрешает оба ограничения, даже если у меня есть Union v w u и Union w v u ограничение, которое, как я думал, было бы лишним.

Что-то мне не хватает? Можно ли сделать что-то подобное в Purescript с помощью библиотеки вариантов?

1 ответ

Если вы хотите производить Variant u используя expand вы должны потребовать, чтобы оба v и w являются подразделами u:

module Main where

import Prelude

import Data.Variant (expand, Variant)
import Prim.Row (class Union)

combine :: forall v v_ w w_ u. Union w w_ u => Union v v_ u =>
     Array (Variant v)
  -> Array (Variant w)
  -> Array (Variant u)
combine arr1 arr2 = map expand arr1 <> map expand arr2

Вот рабочая суть, загруженная в try.purescript.

Другие вопросы по тегам