In a nutshell
Given this function:
> :i set
set ::
( VividAction m -- This isn't important.
, Subset (InnerVars params) sdArgs -- This says `params` is a subset of
-- `sdArgs`, perhaps in a
-- different order.
, VarList params) => -- A `VarList` is just a tuple.
Synth sdArgs -> params -> m ()
and two values params
and params'
that satisfy the second constraint, is it possible to create a third value params''
that combines the information from params
and params'
?
In detail
I use the Vivid library to control SuperCollider from Haskell. Vivid lets you create a "synth", something that makes sound and accepts a number of parameters, and then send messages to it.
Those messages are typed. Sending messages to a synth looks like this:
> :set -XDataKinds
> set mySynth (120 :: I "frequency", 0.1 :: I "amplitude")
> set mySynth () -- Also valid. Messages can have any number of terms.
where "frequency" and "amplitude" should be two of the parameters that mySynth
accepts. If you ask to manipulate a parameter that is not part of the definition of mySynth
, Vivid will complain at compile time. This is reflected in the type of the function set
:
> :i set
set ::
( VividAction m -- This isn't important.
, Subset (InnerVars params) sdArgs -- This says `params` is a subset of
-- `sdArgs`, perhaps in a
-- different order.
, VarList params) => -- A `VarList` is just a tuple.
Synth sdArgs -> params -> m ()
-- Defined in ‘Vivid.Actions’
sdArgs
represents the parameters that the synth accepts, and Subset (InnerVars params) sdArgs
says that params
must be a subset of those. (I believe most, maybe all, of Vivid's fancy type-level code is in the Vivid.SynthDef.TypesafeArgs module.)
My problem is that I'm generating (from a controller called a monome grid, using my library Montevideo) a lot of simultaneous singleton messages like (120 :: I "frequency"). The number of messages seems like it might be overwhelming SuperCollider -- I'm getting dropped notes and hung notes, which to me suggests dropped messages. I'd like to reduce the program's bandwidth by sending those simultaneous messages as one big tuple, rather than sending each one separately. But I don't know what type the combined tuple would be, so I can't create it!
I'd like to write a function like this:
concatTuples ::
( Subset (InnerVars params) sdArgs
, VarList params) =>
[params] -> params
That way, if my synth accepts "freq" and "amp" and "wobble", I can call concatTuples [(1 :: I "wobble"), (440 :: I "freq")]
and expect to get either (1 :: I "wobble", 440 :: I "freq)
or the swap of that.
Can concatTuples
be written?
(EDIT: Joachim Breitner explains that that type signature I've suggested for concatTuples
doesn't make sense. But maybe another one does?)
Something unimportant
An implementation question that arises is how to combine two tuples if they contain elements of the same type -- e.g. both have a frequency. I don't care how that's solved -- use the first, use the second, die -- because it's not a case I'll run into.