【问题标题】:Combine tuples of unknown type satisfying the same constraint组合满足相同约束的未知类型的元组
【发布时间】:2020-09-03 23:24:29
【问题描述】:

简而言之

给定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 ()

以及满足第二个约束的两个值paramsparams',是否可以创建第三个值params'' 结合来自paramsparams' 的信息?

详细说明

我使用 Vivid 库来控制来自 Haskell 的 SuperCollider。 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 将在编译时报错。这体现在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 表示合成器接受的参数,Subset (InnerVars params) sdArgs 表示params 必须是这些参数的子集。 (我相信 Vivid 的大部分(也许是全部)花哨的类型级代码都在 Vivid.SynthDef.TypesafeArgs 模块中。)

我的问题是我正在生成(从一个名为monome grid 的控制器,使用我的库Montevideo)很多同时的单例消息,例如(120 :: I“频率”)。消息的数量似乎可能是压倒性的 SuperCollider —— 我收到了丢弃的笔记和挂起的笔记,这对我来说暗示了丢弃的消息。我想通过将这些同时消息作为一个大元组发送来减少程序的带宽,而不是分别发送每个消息。但是我不知道组合元组是什么类型,所以我不能创建它!

我想写一个这样的函数:

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可以写吗?

(编辑:Joachim Breitner explains 我为concatTuples 建议的那种类型签名没有意义。但也许another one 可以?)

不重要的事情

出现的一个实现问题是,如果两个元组包含相同类型的元素,如何组合它们——例如两者都有频率。我不在乎它是如何解决的——使用第一个,使用第二个,死——因为这不是我会遇到的情况。

【问题讨论】:

  • 注:这个问题的答案对于vivid或supercollider是必要的。
  • 这个问题的动机是 SuperCollider 和 Vivid,但答案与它们中的任何一个都无关。我只是问如何组合元组。 I 类型除了它的幻像 String 参数外不携带任何信息。 I :: "frequency"I :: "gonnorhea" 类型的元素只是带有标签的 Floats。
  • 啊,但是你的concatTuples 不接受元组,它接受VarList 的任意类型约束。所以除非VarList 以某种方式给你这样的能力,否则你不能。 VarList 来自哪个库?猜猜它在这里:hackage.haskell.org/package/vivid-0.4.2.3/docs/…

标签: haskell types constraints supercollider


【解决方案1】:

专注于

我想写一个这样的函数:

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 和/或vivid 做某事,也许更了解vidid 的人可以向您指出如何实现您的实际目标,即如何进行编码这就是你最终不想连接元组。

【讨论】:

  • 啊哈!这很有帮助。我可以改为编写一个函数joinTwoTuples :: params -> params' -> params'',其中这三个类型变量中的每一个都受到相同的约束(所以会有6个而不是2个约束)?然后我可以使用joinTwoTuples折叠一个元组列表吗?
  • 我的问题可能在于是否可以表示该元组列表。我只是尝试了幼稚的方法,GHCI 不服气:评估[(1::I "float"),(2::I "amp")] 会引发错误Couldn't match type ‘"amp"’ with ‘"float"’。如果我可以加入两个元组但不能加入它们的列表,那我就完蛋了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-12
  • 2021-03-16
  • 2019-09-19
  • 2015-08-24
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多