On Thu, 10 Nov 2011, Heinrich Apfelmus wrote:

> Henning Thielemann wrote:
>> On Tue, 8 Nov 2011, Heinrich Apfelmus wrote:
>>
>>> How do you make sure that a new sequence starts on the beat / interleave
>>> nicely with what is still playing?
>>
>> The trick is to update the program but not the currently processed term.
>> Thus the same term can get a new meaning. The advantage is that I can
>> break a loop and redirect it to somewhere else, e.g. by changing
>>
>>> loop1 = append melody loop1 ;
>>
>> to
>>
>>> loop1 = append melody loop2 ;
>>
>> but the melody keeps running and is not interrupted. The disadvantage is
>> that I cannot break a call to "cycle" and that after program change, the
>> current term may refer to functions that are no longer defined.
>
> Nice! And that's also why you've implemented a custom functional language?

The language should be just Haskell. Actually the modules can be loaded 
into GHCi. It would be nice have some infrastructure for Haskell 
processing such that we do not need to re-implement GHC in the end.

> I do wonder about the precise semantics of changing expressions 
> in-flight, though. For instance, imagine that the program is performing 
> a time-consuming computation that does not (yet) produce any sound, what 
> will happen if I update the term that is being evaluated? Or will 
> updates only take effect at certain "checkpoints", namely whenever a new 
> MIDI note is created and passed to the synthesizer? How do you detect 
> which terms have changed and which haven't?

The music is described by a list of MIDI events and Wait commands. The 
rewrite engine accepts changes of the program after every list item. 
However the current term is not immediately affected by a program change. 
If the current term is

  append melody loop

and a program update changes the meaning of "loop", then "melody" will be 
played as before and only when "loop" is reached the update to the program 
becomes audible.


> Do you have any formal model of how exactly this works? With a formal
> model, it might be possible to concoct an implementation that can embed
> the DSL into Haskell.

I am afraid from the point of view of formal languages this is an ugly 
hack. You have no referential transparency. E.g. as noted above at time 
point zero the term 'loop' may refer to 'NoteOn 23' and two seconds later 
it may refer to 'PgmChange 42'. The whole matter of sharing and buffering 
of reduced terms is no longer an issue of performance but an issue of the 
semantics. As I said above,

  loop1 = append melody loop1

allows you to continue with 'loop2' after 'loop1' by changing it to

  loop1 = append melody loop2

on the fly, but if you would have written

  loop1 = cycle melody

in the first place, this would not be possible. (Only by changing the 
definition of 'cycle'.)


On the other hand you can consider live editing of the program as a phase 
of development and debugging. You may finally decide to just run the 
program and play the music without any modifications. In this case you 
have a clean referentially transparent language.
_______________________________________________
haskell-art mailing list
haskell-art@lurk.org
http://lists.lurk.org/mailman/listinfo/haskell-art

Reply via email to