I have been playing around with Purescript as a means of experimenting with programming in a Haskell-like language with row and column polymorphism.
In particular, using Purescript's variant package, I was trying to write an operation to combine two lists list of "notes" sequentially, where the two lists have possibly disjoint sets of variants. The idea here is to allow users to be able to combine scores declared on some sub-set of notes to be automatically combined with scores containing a super-set, without preforming any explicit conversions.
For example, given the following boilerplate to make working with the variants easier:
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"
I can define the following types:
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)
And given those, I can define two scores:
score1 :: Array CPentatonic
score1 = [inj _A A,inj _C C]
score2 :: Array CNatural
score2 = [inj _C C, inj _B B]
So, to combine them, I want a function of signature
combine :: forall v w u. Union w v u =>
Array (Variant v)
-> Array (Variant w)
-> Array (Variant u)
However, my attempt at this:
combine x y = (map expand x) <> (map expand y)
yields
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.
If I try changing the Union v w u
constraint to a Union w v u
constraint, the error goes back and forth between the first map expand
, and the second map expand
, but nothing I do seems to resolve both constraints, even if I have both a Union v w u
and a Union w v u
constraint, which I thought would have been redundant.
Is there something I'm missing? Is it possible to do something like this in Purescript using the variant library?
If you want to produce Variant u
by using expand
you have to require that both v
and w
are subrows of 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 loaded into try.purescript.