В двух словах
Учитывая эту функцию:
> :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 ()
и два значения params
и params'
, удовлетворяющие второму ограничению, возможно ли создать третье значение params''
, объединяющее информацию из params
и params'
?
В деталях
Я использую библиотеку Vivid для управления SuperCollider от Haskell. Vivid позволяет вам создать синтезатор, что-то, что воспроизводит звук и принимает ряд параметров, а затем отправлять ему сообщения.
Эти сообщения печатаются. Отправка сообщений синтезатору выглядит так:
> :set -XDataKinds
> set mySynth (120 :: I "frequency", 0.1 :: I "amplitude")
> set mySynth () -- Also valid. Messages can have any number of terms.
где частота и амплитуда должны быть двумя параметрами, которые принимает mySynth
. Если вы попросите манипулировать параметром, который не является частью определения mySynth
, Vivid будет жаловаться во время компиляции. Это отражено в типе функция 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
представляет параметры, которые принимает синтезатор, а Subset (InnerVars params) sdArgs
говорит, что params
должно быть их подмножеством. (Я полагаю, что большая часть, а может быть, и весь причудливый код Vivid на уровне типов находится в Vivid.SynthDef.TypesafeArgs.)
Моя проблема в том, что я генерирую (из контроллера, называемого мономной сетки, используя мою библиотеку Montevideo) много одновременных одноэлементных сообщений, таких как (120 :: I частота). Кажется, что количество сообщений может быть огромным SuperCollider — я получаю пропущенные заметки и зависшие заметки, что, на мой взгляд, предполагает пропущенные сообщения. Я хотел бы уменьшить пропускную способность программы, отправляя эти одновременные сообщения как один большой кортеж, а не отправляя каждое отдельно. Но я не знаю, какого типа будет объединенный кортеж, поэтому я не могу его создать!
Я хотел бы написать такую функцию:
concatTuples ::
( Subset (InnerVars params) sdArgs
, VarList params) =>
[params] -> params
Таким образом, если мой синтезатор принимает частоту, усиление и колебания, я могу вызвать concatTuples [(1 :: I "wobble"), (440 :: I "freq")]
и ожидать получить либо (1 :: I "wobble", 440 :: I "freq)
, либо их замену.
Можно ли написать concatTuples
?
(EDIT: Иоахим Брайтнер объясняет, что подпись типа, которую я предложил для concatTuples
, не имеет смысла. Но, может быть, другой делает?)
Что-то неважное
Возникающий вопрос реализации заключается в том, как объединить два кортежа, если они содержат элементы одного типа, например. оба имеют частоту. Меня не волнует, как это будет решено — используйте первое, используйте второе, умрите — потому что это не тот случай, с которым я столкнусь.
I
не несет никакой информации, кроме своего фантомного параметраString
. Элементы типаI :: "frequency"
илиI :: "gonnorhea"
— это простоFloat
с прикрепленными метками. - person Jeffrey Benjamin Brown   schedule 03.09.2020concatTuples
не принимает кортежи, он принимает ограничения произвольных типов с помощьюVarList
. Так что еслиVarList
каким-то образом не даст вам такую возможность, вы не сможете. Из какой библиотекиVarList
? Думаю, это здесь: хакер. haskell.org/package/vivid-0.4.2.3/docs/ - person Joachim Breitner   schedule 03.09.2020