在纯脚本中组合不同类型的变体列表
Combining lists of variants of different types in 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 中执行类似的操作?
如果你想使用 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
Here is a working gist 加载到 try.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 中执行类似的操作?
如果你想使用 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
Here is a working gist 加载到 try.purescript.