Объединить кортежи неизвестного типа, удовлетворяющие одному и тому же ограничению

В двух словах

Учитывая эту функцию:

> :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, не имеет смысла. Но, может быть, другой делает?)

Что-то неважное

Возникающий вопрос реализации заключается в том, как объединить два кортежа, если они содержат элементы одного типа, например. оба имеют частоту. Меня не волнует, как это будет решено — используйте первое, используйте второе, умрите — потому что это не тот случай, с которым я столкнусь.


person Jeffrey Benjamin Brown    schedule 01.09.2020    source источник
comment
NB: Ответ на этот вопрос нужен конкретно для яркого или суперколлайдера.   -  person Joachim Breitner    schedule 02.09.2020
comment
Вопрос мотивирован SuperCollider и Vivid, но ответ не имеет ничего общего ни с одним из них. Я только спрашиваю, как комбинировать кортежи. Тип I не несет никакой информации, кроме своего фантомного параметра String. Элементы типа I :: "frequency" или I :: "gonnorhea" — это просто Float с прикрепленными метками.   -  person Jeffrey Benjamin Brown    schedule 03.09.2020
comment
Ах, но ваш concatTuples не принимает кортежи, он принимает ограничения произвольных типов с помощью VarList. Так что если VarList каким-то образом не даст вам такую ​​возможность, вы не сможете. Из какой библиотеки VarList? Думаю, это здесь: хакер. haskell.org/package/vivid-0.4.2.3/docs/   -  person Joachim Breitner    schedule 03.09.2020


Ответы (1)


Сосредоточившись только на

Я хотел бы написать такую ​​функцию:

concatTuples ::
 ( Subset (InnerVars params) sdArgs
 , VarList params) =>
     [params] -> params

Таким образом, если мой синтезатор принимает частоту, усиление и колебание, я могу вызвать concatTuples [(1 :: I "wobble"), (440 :: I "freq")] и ожидать получить либо (1 :: I "wobble", 440 :: I "freq"), либо их замену.

Это невозможно: concatTuples имеет один параметр типа, params, и в вызове concatTuples он может обозначать только один конкретный тип.

Значения, которые вы хотите передать в вашем примере, имеют другой тип (а именно I "wobble" и ( I "wobble", I "freq")). Это не может работать.

У меня сложилось впечатление, что вы хотите сделать что-то очень однообразным способом для Haskell и/или Vivid, и, возможно, кто-то, кто лучше разбирается в vidid, может указать вам, как приблизиться к вашей реальной цели, то есть как приступить к кодированию того, что вы не заканчивайте тем, что хотите конкатенировать кортежи.

person Joachim Breitner    schedule 03.09.2020
comment
Ага! Это полезно. Могу ли я вместо этого написать функцию joinTwoTuples :: params -> params' -> params'', в которой каждая из этих трех переменных типа подчиняется одним и тем же ограничениям (таким образом, будет 6 ограничений вместо 2)? И тогда я мог бы свернуть список кортежей, используя joinTwoTuples? - person Jeffrey Benjamin Brown; 03.09.2020
comment
Мой вопрос может сводиться к тому, может ли быть представлен этот список кортежей. Я просто попробовал наивный способ, и GHCI не был убежден: оценка [(1::I "float"),(2::I "amp")] вызывает ошибку Couldn't match type ‘"amp"’ with ‘"float"’. Если я могу присоединиться к двум кортежам, но не могу присоединиться к их списку, мне конец. - person Jeffrey Benjamin Brown; 03.09.2020