我一直在尝试使用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中使用变体库执行类似的操作?
如果要使用expand
生成Variant u
,则必须要求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.中的工作要点