[livecode] Re: Vivid: Create a value of type `I a` where `a` is chosen at runtime

From: <amindfv_at_gmail.com>
Date: Sat, 7 Jul 2018 13:52:07 -0400

Awesome, thanks Jeffrey! I'm also slowly backfilling vivid-synth.com with an FAQ, with answers I've sent via email to people (including you, Jeffrey) who've emailed with questions.

It's a large system to write docs for, so I'm sort of lazily-evaluating them. To force evaluation of some documentation, email and ask a question!

Tom

> El 7 jul 2018, a las 13:25, Jeffrey Brown <jeffbrown.the_at_gmail.com> escribió:
>
> Bah! I could have caught that.
>
> It works now! Thanks, Tom!
>
> I don't know if this is of interest to anyone, but I'm building a collection of examples of how to do simple tasks in Vivid at https://github.com/JeffreyBenjaminBrown/vivid/tree/jbb/learning
>
>> On Sat, Jul 7, 2018 at 12:02 AM <amindfv_at_gmail.com> wrote:
>> Whoops, that's a not-very-nice error message saying it can't set the "foobar" property of the synth because it doesn't have that property. If you remove that line it'll work.
>>
>> Tom
>>
>>
>>> El 6 jul 2018, a las 21:20, Jeffrey Brown <jeffbrown.the_at_gmail.com> escribió:
>>>
>>> > no maximum
>>>
>>> Nice!
>>>
>>> > Here's how I might
>>>
>>> After half an hour of study I haven't figured out how to evaluate that.
>>>
>>> > :{
>>> *Main|
>>> *Main| main = do
>>> *Main| s <- synth boop ()
>>> *Main|
>>> *Main| -- Randomly pick one from the list:
>>> *Main| set' <- pick ( [ \n -> set s (toI n :: I "freq")
>>> *Main| , \n -> set s (toI n :: I "amp")
>>> *Main| , \n -> set s (toI n :: I "foobar")
>>> *Main| ] -- :: [(Real n, VividAction m) => n -> m ()]
>>> *Main| )
>>> *Main| set' 35
>>> *Main| :}
>>>
>>> <interactive>:208:26: error:
>>> • Could not deduce: Elem "foobar" '[] arising from a use of ‘set’
>>> from the context: (MonadRandom m, VividAction m)
>>> bound by the inferred type of
>>> main :: (MonadRandom m, VividAction m) => m ()
>>> at <interactive>:(202,1)-(211,9)
>>> • In the expression: set s (toI n :: I "foobar")
>>> In the expression: \ n -> set s (toI n :: I "foobar")
>>> In the first argument of ‘pick’, namely
>>> ‘([\ n -> set s (toI n :: I "freq"),
>>> \ n -> set s (toI n :: I "amp"),
>>> \ n -> set s (toI n :: I "foobar")])’
>>>
>>>
>>>> On Fri, Jul 6, 2018 at 2:28 PM <amindfv_at_gmail.com> wrote:
>>>> Interesting solution! Here's how I might solve it (wanting to set a random parameter of a synth that's playing):
>>>>
>>>> s <- synth foo ()
>>>>
>>>> -- Randomly pick one from the list:
>>>> set' <- pick [
>>>> \n -> set s (toI n :: I "freq")
>>>> , \n -> set s (toI n :: I "amp")
>>>> , \n -> set s (toI n :: I "foobar")
>>>> ]
>>>>
>>>> set' 35
>>>>
>>>> (You can eliminate the "\n ->" too but thought I'd show the more general case)
>>>>
>>>> To answer your specific questions:
>>>> - Yes, it's definitely intentional that Vivid only lets you set parameters the synth has. If you really need to get around it I've built in a few escape hatches (which I can describe), but I've used Vivid nearly every day for a few years now and haven't needed it so far.
>>>>
>>>> - There's no maximum to the number of arguments set' could have. In the worst case (thousands of them?) it could slow down your compilation, but it shouldn't slow down runtime at all.
>>>>
>>>> Tom
>>>>
>>>>> El 5 jul 2018, a las 00:51, Jeffrey Brown <jeffbrown.the_at_gmail.com> escribió:
>>>>>
>>>>> It works!
>>>>>
>>>>> set' :: (Subset '["freq","amp"] sdArgs, Real n, VividAction m)
>>>>> => String -> Node sdArgs -> n -> m ()
>>>>> set' "freq" s n = set s (toI n :: I "freq")
>>>>> set' "amp" s n = set s (toI n :: I "amp")
>>>>>
>>>>> This has a property that, depending on your point of view, you could call a disadvantage or a feature: `set'` can only send messages to synths (`Node`s) for which "freq" and "amp" are both valid parameters. If you wanted to use it with a lot of unique synths, and their parameters have unique names, then you would have to make every synth recognize all the parameters of all the others. (Those extra parameters could be no-ops, part of the type signature but unused in the definition.)
>>>>>
>>>>> I'm in kind of a weird place, fighting with Vivid's brilliant type safety.
>>>>>
>>>>> Is there a theoretical maximum to the number of parameter names `set'` could be defined for? I tried 33 and it compiled.
>>>>>
>>>>>
>>>>>> On Wed, Jul 4, 2018 at 9:31 PM Jeffrey Brown <jeffbrown.the_at_gmail.com> wrote:
>>>>>> Thanks, Claude! I'm working on moving your example into the Vivid context.
>>>>>>
>>>>>> Tom, indeed, that would be simpler! I wanted to use `toI`. But I don't see how to do that without hard-coding every choice of which parameter to send a message to.
>>>>>>
>>>>>> For instance, suppose you've got a list of parameter names `["freq","amp" ..]` from which you want the code to choose a parameter `p` randomly every cycle, and set it to the value `x`. You can't write `set s (x :: I p)`, because the `p` in `I p` is a type-level variable rather than an ordinary one.
>>>>>>
>>>>>> I considered keeping a list of functions `[setFreq, setAmp ..]` instead of a list of parameter names, but I haven't found how to represent such a list:
>>>>>> .
>>>>>> > :set -XDataKinds
>>>>>> > :set -XRankNTypes
>>>>>> > s <- synth boop ()
>>>>>> > [set s (3::I "amp"), set s (5::I "freq")]
>>>>>>
>>>>>> <interactive>:194:22: error:
>>>>>> • Could not deduce: Elem "freq" '[] arising from a use of ‘set’
>>>>>> from the context: VividAction m
>>>>>> bound by the inferred type of it :: VividAction m => [m ()]
>>>>>> at <interactive>:194:1-41
>>>>>> • In the expression: set s (5 :: I "freq")
>>>>>> In the expression: [set s (3 :: I "amp"), set s (5 :: I "freq")]
>>>>>> In an equation for ‘it’:
>>>>>> it = [set s (3 :: I "amp"), set s (5 :: I "freq")]
>>>>>> >
>>>>>>
>>>>>>
>>>>>>> On Wed, Jul 4, 2018 at 11:50 AM <amindfv_at_gmail.com> wrote:
>>>>>>> The approach I'd use might be a little different. Vivid offers a "toI" function which takes any number and converts it to an "I".
>>>>>>>
>>>>>>> So for example:
>>>>>>>
>>>>>>> ```
>>>>>>> myNums = [1..10] :: [Double]
>>>>>>>
>>>>>>> sd0 = undefined :: SynthDef '["freq"]
>>>>>>> sd1 = undefined :: SynthDef '["amp"]
>>>>>>>
>>>>>>> main = do
>>>>>>> s0 <- synth sd0
>>>>>>> s1 <- synth sd1
>>>>>>> forM_ myNums $ \n -> do
>>>>>>> set s0 (toI n :: I "freq")
>>>>>>> set s1 (toI n :: I "amp")
>>>>>>> ```
>>>>>>>
>>>>>>> Also: "toI" works on any numeric type (any "Real n"), and "I" itself is a numeric type. So you can always write:
>>>>>>>
>>>>>>> x = 5 :: I "freq"
>>>>>>> y = toI x :: I "amp"
>>>>>>>
>>>>>>> Tom
>>>>>>>
>>>>>>>
>>>>>>>> El 4 jul 2018, a las 08:30, Jeffrey Brown <jeffbrown.the_at_gmail.com> escribió:
>>>>>>>>
>>>>>>>> Composers reuse melodic material across different instruments. I would like to do that in Vivid. I would keep a sequence of values and send it sometimes to one parameter of one synth, sometimes to a different parameter of a different synth.
>>>>>>>>
>>>>>>>> To do that I would have to coerce those numbers to values of type `I a`, where the string `a` is known only at runtime. I tried to write a function to do that:
>>>>>>>>
>>>>>>>> import GHC.TypeLits
>>>>>>>> toIOf :: (Real n, GHC.TypeLits.KnownSymbol a) => String -> n -> I a
>>>>>>>> toIOf "freq" n = toI n :: I "freq"
>>>>>>>> toIOf "amp" n = toI n :: I "amp"
>>>>>>>>
>>>>>>>> but it won't compile, because the outputs of `toIOf "freq"` and `toIOf "amp"` have different types.
>>>>>>>>
>>>>>>>> Is this possible?
>>>>>>>>
>>>>>>>> --
>>>>>>>> Jeff Brown | Jeffrey Benjamin Brown
>>>>>>>> Website | Facebook | LinkedIn(spammy, so I often miss messages here) | Github
>>>>>>>> _______________________________________________
>>>>>>>> Livecode mailing list -- livecode_at_we.lurk.org
>>>>>>>> To unsubscribe send an email to livecode-leave_at_we.lurk.org
>>>>>>> _______________________________________________
>>>>>>> Livecode mailing list -- livecode_at_we.lurk.org
>>>>>>> To unsubscribe send an email to livecode-leave_at_we.lurk.org
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Jeff Brown | Jeffrey Benjamin Brown
>>>>>> Website | Facebook | LinkedIn(spammy, so I often miss messages here) | Github
>>>>>
>>>>>
>>>>> --
>>>>> Jeff Brown | Jeffrey Benjamin Brown
>>>>> Website | Facebook | LinkedIn(spammy, so I often miss messages here) | Github
>>>>> _______________________________________________
>>>>> Livecode mailing list -- livecode_at_we.lurk.org
>>>>> To unsubscribe send an email to livecode-leave_at_we.lurk.org
>>>> _______________________________________________
>>>> Livecode mailing list -- livecode_at_we.lurk.org
>>>> To unsubscribe send an email to livecode-leave_at_we.lurk.org
>>>
>>>
>>> --
>>> Jeff Brown | Jeffrey Benjamin Brown
>>> Website | Facebook | LinkedIn(spammy, so I often miss messages here) | Github
>>> _______________________________________________
>>> Livecode mailing list -- livecode_at_we.lurk.org
>>> To unsubscribe send an email to livecode-leave_at_we.lurk.org
>> _______________________________________________
>> Livecode mailing list -- livecode_at_we.lurk.org
>> To unsubscribe send an email to livecode-leave_at_we.lurk.org
>
>
> --
> Jeff Brown | Jeffrey Benjamin Brown
> Website | Facebook | LinkedIn(spammy, so I often miss messages here) | Github
> _______________________________________________
> Livecode mailing list -- livecode_at_we.lurk.org
> To unsubscribe send an email to livecode-leave_at_we.lurk.org


_______________________________________________
Livecode mailing list -- livecode_at_we.lurk.org
To unsubscribe send an email to livecode-leave_at_we.lurk.org
Received on Sat Jul 07 2018 - 17:52:29 BST

This archive was generated by hypermail 2.4.0 : Sun Aug 20 2023 - 16:02:23 BST