[Haskell-cafe] pointers for EDSL design

John Lato jwlato at gmail.com
Wed Oct 6 12:36:02 EDT 2010

Hi Stephen,

> From: Stephen Tetley <stephen.tetley at gmail.com>
> Hi John
> For the user level stuff, I don't think CSound really has "functions"
> - either for the score or orchestra. The score I think is just a list
> of /notes/ with many, many parameters and the orchestra is a graph
> description saying how the UGens are connected.

This is good news - I believe Pan, Feldspar, Lava etc. generate
> functions or procedures in the output code which means they have to
> involve the complicated techniques for embedding lambdas and functions
> in the EDSL. If they didn't, there would be massive code blow up.
> However because CSound is more or less "straight line" code - i.e.
> lines are interpreted sequentially, there are no procedures or
> functions to define and call - generating it should be much simpler.

Yes, exactly.  I'm not interested in anything nearly as sophisticated, so
 those aren't great examples for me.

> Andy Gill's Dot package on Hackage has a crafty, but simple technique
> to allow you to reference graph nodes and link them within a monad and
> output as "foreign" code - here dot files. Something similar might be
> satisfactory for orchestra files.

The orchestra graph is basically the issue I'm looking at (ignoring the
score for now).  My first implementation used an Orch monad very similar to
the one used in Andy Gill's dotgen.  It worked and the implementation was
very straightforward, however I wanted to see if it was possible to create a
non-monadic interface.  That is, change my classes from

class GenM repr a where
  sigGenM :: a -> repr (ASig repr)


class Gen repr a where
  sigGen :: repr a -> repr (ASig repr)

This is in tagless-final style (which really is slick BTW); that's why
everything is represented through type classes.

The second version is really the one I want to use, although it was more
work to implement.  For the Csound interpreter, I needed a naming mechanism
like TH's Q monad, along with some other machinery.

So here's a very simple expression:

t1 = let v = sigGen (cnst 1) in outs v v

which is what led to my question.  I'm binding the sigGen to 'v' to
introduce sharing at the meta-level.  Would it be better to introduce
support for this in the dsl?

Anyway, here are a few simple test expressions to provide the flavor of what
I'm doing:

-- additive synthesis, 20 partials of constant amplitude
t6 = let so = sum . zipWith (oscil (cnst 1000)) [ cnst (110*f) | f <- [4..]]
(replicate 20 1)
    in outs so so

-- stacked frequency modulation using 4 oscillators
t8 = let stack = foldr ($) (csig 40) (replicate 4 \fq -> oscil (cnst 1000)
fq 1) in outs stack stack

The edsl provides the functions "oscil", "cnst", "csig", and "outs", but
most of the magic happens in the csound interpreter.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20101006/0587928d/attachment.html

More information about the Haskell-Cafe mailing list