问题描述
简而言之
> :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''
和{{1 }}?
详细信息
我使用Vivid库从Haskell控制SuperCollider。 Vivid使您可以创建“合成器”,使声音发出声音并接受许多参数,然后向其发送消息。
键入这些消息。将消息发送到合成器看起来像这样:
params
其中“频率”和“振幅”应为params'
接受的两个参数。如果您要求操纵不属于> :set -XDataKinds
> set mySynth (120 :: I "frequency",0.1 :: I "amplitude")
> set mySynth () -- Also valid. Messages can have any number of terms.
定义的参数,Vivid将在编译时抱怨。这反映在the function set
的类型中:
mySynth
mySynth
表示合成器接受的参数,> :i set
set ::
( VividAction m -- This isn't important.,VarList params) => -- A `VarList` is just a tuple.
Synth sdArgs -> params -> m ()
-- Defined in ‘Vivid.Actions’
表示sdArgs
必须是这些参数的子集。 (我相信Vivid的大多数花哨的类型级代码可能都在Vivid.SynthDef.TypesafeArgs模块中。)
我的问题是,我正在使用我的库monome grid从称为Montevideo的控制器生成许多同时发生的单例消息,例如(120 :: I“ frequency”)。消息的数量似乎使SuperCollider不堪重负-我收到的便条和挂起的便条,对我来说,这意味着已丢弃的消息。我想通过将那些同时发送的消息作为一个大元组发送,而不是分别发送每个消息,以减少程序的带宽。但是我不知道合并的元组是什么类型,所以我无法创建它!
Subset (InnerVars params) sdArgs
这样,如果我的合成器接受“ freq”,“ amp”和“ wobble”,我可以打电话给params
并期望得到concatTuples ::
( Subset (InnerVars params) sdArgs,VarList params) =>
[params] -> params
或交换它。
可以写concatTuples [(1 :: I "wobble"),(440 :: I "freq")]
吗?
(编辑:Joachim Breitner explains我为(1 :: I "wobble",440 :: I "freq)
建议的类型签名没有意义。但是也许another one有用吗?)
有些不重要
出现的实现问题是,如果两个元组包含相同类型的元素,则该如何合并-例如两者都有频率。我不在乎如何解决-使用第一个,使用第二个,死掉-因为我不会遇到这种情况。
解决方法
仅关注
我想写一个像这样的函数:
concatTuples :: ( Subset (InnerVars params) sdArgs,VarList params) => [params] -> params
这样,如果我的合成器接受“ freq”,“ amp”和“ wobble”,我可以 致电concatTuples
[(1 :: I "wobble"),(440 :: I "freq")]
,并期望 得到(1 :: I "wobble",440 :: I "freq")
或交换它。
这是不可能的:concatTuples
有一个类型参数params
,在对concatTuples
的调用中,它只能代表一种特殊类型。
在示例中要传入和传出的值是不同类型的(即I "wobble"
和( I "wobble",I "freq")
)。这行不通。
我的印象是您想以一种非常独特的方式为Haskell做事和/或生动活泼,也许有人更了解vidid可以为您指出如何实现您的实际目标,即如何进行编码这就是您最终不想连接元组的原因。