
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way. I have a problem that is very state-ful and I keep thinking of it as OO, which is driving me crazy. Haskell is several times harder to use than Python in this instance, probably because I'm doing it wrong. To give you a larger context, this problem is essentially compiling a description of music (my own) into a kind of music-machine-language (CSound). CSound is relatively untidy. In this one example, in a OO way of thinking, I have data called AssignedNumbers that assigns integers to unique strings and keeps track of the used integers and next available integer (the choice of available integer could follow a number of conventions so I wanted to hide that in an ADT.) So it has an associated function: getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers) What getNumber does is: - check if the string already has a number assigned to it. If so, return that number. - if not, pick the next available number. - in all cases, return the possibly changed state of AssignedNumbers Then in a larger data structure, it contains fields of type AssignedNumbers. Like data MusicStuff = MusicStuff { oscillatorNumbers :: AssignedNumbers , tableNumbers :: AssignedNumbers , ... } I'm using MusicStuff in a State monad, so I might write a function like doSomeMusicStuff :: String -> String -> State MusicStuff (Int,Int) doSomeMusicStuff aString1 aString2 = do ms <- get (o1,newOscNums) = getNumber aString1 (oscillatorNumbers ms) (t1,newTabNums) = getNumber aString2 (tableNumbers ms) put ms { oscillatorNumbers = newOscNums , tableNumbers = newTabNums } return (o1,t1) For what it does, this is extremely verbose and filled with distracting visual content. And this is just a very simple example---my real problem is several times more state-ful. Is there a better way? Note that in Python it would be a method def doMusicStuff( self, s1, s2 ) : return (self.oscillatorNumbers.next(s1), self.oscillatorNumbers.next(s2))

Please check out Paul Hudak's page. http://cs-www.cs.yale.edu/homes/hudak-paul/ On Tue, 01 Dec 2009 17:01:29 -0800, you wrote:
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.
I have a problem that is very state-ful and I keep thinking of it as OO, which is driving me crazy. Haskell is several times harder to use than Python in this instance, probably because I'm doing it wrong.
To give you a larger context, this problem is essentially compiling a description of music (my own) into a kind of music-machine-language (CSound). CSound is relatively untidy.
In this one example, in a OO way of thinking, I have data called AssignedNumbers that assigns integers to unique strings and keeps track of the used integers and next available integer (the choice of available integer could follow a number of conventions so I wanted to hide that in an ADT.) So it has an associated function:
getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers)
What getNumber does is:
- check if the string already has a number assigned to it. If so, return that number.
- if not, pick the next available number.
- in all cases, return the possibly changed state of AssignedNumbers
Then in a larger data structure, it contains fields of type AssignedNumbers. Like
data MusicStuff = MusicStuff { oscillatorNumbers :: AssignedNumbers , tableNumbers :: AssignedNumbers , ... }
I'm using MusicStuff in a State monad, so I might write a function like
doSomeMusicStuff :: String -> String -> State MusicStuff (Int,Int) doSomeMusicStuff aString1 aString2 = do ms <- get (o1,newOscNums) = getNumber aString1 (oscillatorNumbers ms) (t1,newTabNums) = getNumber aString2 (tableNumbers ms) put ms { oscillatorNumbers = newOscNums , tableNumbers = newTabNums } return (o1,t1)
For what it does, this is extremely verbose and filled with distracting visual content. And this is just a very simple example---my real problem is several times more state-ful. Is there a better way?
Note that in Python it would be a method
def doMusicStuff( self, s1, s2 ) : return (self.oscillatorNumbers.next(s1), self.oscillatorNumbers.next(s2))
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Regards, Casey

Thanks for the reply. Was there something specific you were referring to, or just the idea that he wrote Haskore? Haskore is not very closely related to what I'm trying to do. I believe he has a CSound back end for Haskore, but it is in a rough state and not closely related to what I'm trying to do. Most computer music packages have a fairly well-defined idea of a musical event, and events usually get translated one-to-one into another language. I have a quite messy problem which is describable as a big state machine, at least in the way I think of it. An input "event" can trigger a cascade of changes to the state. Channel numbers must be assigned and tracked, table numbers as well, decisions about whether to create a new table or re-use an old one, global variables and commands added and/or modified, etc. So I am hoping for a comment from that perspective. Thanks, Mike Casey Hawthorne wrote:
Please check out Paul Hudak's page.

On Tue, Dec 1, 2009 at 7:55 PM, Michael Mossey
Thanks for the reply. Was there something specific you were referring to, or
Maybe http://plucky.cs.yale.edu/cs431/reading.htm Chapter 9 "An Algebra of Music."

Hi Gregg, Yes, I've read his book School of Expression and I'll have to check up on this draft. His ideas are very useful at the level of composing music, where an algebraic representation is natural and flies free and high. It's when that representation grinds against an old quaint system like CSound that things get ugly. However, I have a new idea. Stay tuned. -Mike Gregg Reynolds wrote:
On Tue, Dec 1, 2009 at 7:55 PM, Michael Mossey
mailto:mpm@alumni.caltech.edu> wrote: Thanks for the reply. Was there something specific you were referring to, or
Maybe http://plucky.cs.yale.edu/cs431/reading.htm Chapter 9 "An Algebra of Music."

Hi Mike
There used to be some slides available commenting on Haskore's CSound
interface. But they seem to have vanished (I have a copy rendered to
pdf when they were available). Like all slide presentations there's a
lot of reading between the lines to get a good picture after the fact:
http://www.nepls.org/Events/16/abstracts.html#hudak
http://plucky.cs.yale.edu/cs431/HasSoundNEPLS-10-05.ppt -- vanished
Maybe you're doomed to frustration though trying to implement your
system in "Haskell". For the argument I'm about to make, I'd say a
working programming language has two things - syntax, semantics and
libraries and a repertory of prior art. Stateful programming clearly
has some syntax burden in Haskell, stateful monadic programming has
some benefit of 'stratification' - you have precise control of 'what
state is where'. It's a matter of taste whether you like Python's
flexibility or Haskell's, erm, 'locality' (precision?).
As for the second half of what you get from a programming language,
your system description frames what you want to do with an emphasis on
dynamic aspects. This seems a good way off from the prior art in
Haskell. For instance there are Haskell synthesizers - George
Giorgidze's yampa-synth and Jerzy Karczmarczuk's Clarion (actually in
Clean, but near enough). Here you build signal processing modules -
unit generators, of course - Yampasynth uses arrows to do this Clarion
uses infinite streams. With both you would build a synthesizer
statically from unit generators and somehow run it to produce
sounds[1].
There is also the prior art of embedded hardware description
languages, Lava, Hydra, Wired, Gordon Pace's HeDLa, soon Kansas Lava.
One could view constructing synthesizers from unit generators as
usefully analogous to constructing circuits - and certainly if you are
'compiling' to another system to do do the real work (in your case
CSound) the papers on Wired, HeDLa, and Kansas Lava have useful
insights on 'offshoring' compilation. But again these systems have
strong bearing in the 'static description' of a circuit rather than
its dynamical operation.
If neither of those 'genres' is close to what you really want to do
then the Haskell prior art is running a bit thin. You could look at
dataflow - the dynamic PD / Max systems are often describe as a
dataflow systems. There are some outposts in Haskell of dataflow
programming - Gordon Pace has an embedding of Lustre available from
his homepage and there has been work on dataflow programming via
comonads. There is also reactive programming, but musical examples are
thin on the ground
(nonexistent?) so it might be a long haul to come up with something.
Best wishes
Stephen
[1] This seems a bit of a paraphrase of Yampasynth - which I think
allows you to
define a synthesizer statically in code, but then play it interactively.
2009/12/2 Michael Mossey
Thanks for the reply. Was there something specific you were referring to, or just the idea that he wrote Haskore? Haskore is not very closely related to what I'm trying to do.

Stephen Tetley wrote:
Hi Mike
There used to be some slides available commenting on Haskore's CSound interface. But they seem to have vanished (I have a copy rendered to pdf when they were available). Like all slide presentations there's a lot of reading between the lines to get a good picture after the fact:
http://www.nepls.org/Events/16/abstracts.html#hudak http://plucky.cs.yale.edu/cs431/HasSoundNEPLS-10-05.ppt -- vanished
This looks like a great resource. Maybe Dr. Hudak can get me a copy. He clearly has the experience to implement a CSound "compiler" as gracefully as anyone could.
Maybe you're doomed to frustration though trying to implement your system in "Haskell". For the argument I'm about to make, I'd say a working programming language has two things - syntax, semantics and libraries and a repertory of prior art. Stateful programming clearly has some syntax burden in Haskell, stateful monadic programming has some benefit of 'stratification' - you have precise control of 'what state is where'. It's a matter of taste whether you like Python's flexibility or Haskell's, erm, 'locality' (precision?).
As for the second half of what you get from a programming language, your system description frames what you want to do with an emphasis on dynamic aspects. This seems a good way off from the prior art in Haskell. For instance there are Haskell synthesizers - George Giorgidze's yampa-synth and Jerzy Karczmarczuk's Clarion (actually in Clean, but near enough). Here you build signal processing modules - unit generators, of course - Yampasynth uses arrows to do this Clarion uses infinite streams. With both you would build a synthesizer statically from unit generators and somehow run it to produce sounds[1].
There is also the prior art of embedded hardware description languages, Lava, Hydra, Wired, Gordon Pace's HeDLa, soon Kansas Lava. One could view constructing synthesizers from unit generators as usefully analogous to constructing circuits - and certainly if you are 'compiling' to another system to do do the real work (in your case CSound) the papers on Wired, HeDLa, and Kansas Lava have useful insights on 'offshoring' compilation. But again these systems have strong bearing in the 'static description' of a circuit rather than its dynamical operation.
Thanks for this detailed review. I will investigate these things. My system sits halfway between a low-level signal processor language like CSound and a high-level music description language like Hudak's Haskore. My work as a composer will be done at the highest level possible, which means thinking in terms of "notes"---things that go "boo" at a certain time, place, frequency, amplitude, timbre, etc. But I want to express things beyond, say, MIDI, like indicating that a group of notes should be played legato---which doesn't mean "play them individually with no separation of notes" but actually means "modify the csound instrument's behavior at the time of note connections." So in one small breath I can say, "Make this legato" and at the low level the elves are scurrying around like mad, rearranging code, changing out instruments, merging notes, etc. I also have a bad case of "Not Invented Here Syndrome"---seriously, I want to use this system to do experimental composition, by which I mean any crazy idea I dream up can be implemented by adding to or modifying my system, which gives me a preference to write it myself.
If neither of those 'genres' is close to what you really want to do then the Haskell prior art is running a bit thin. You could look at dataflow - the dynamic PD / Max systems are often describe as a dataflow systems. There are some outposts in Haskell of dataflow programming - Gordon Pace has an embedding of Lustre available from his homepage and there has been work on dataflow programming via comonads. There is also reactive programming, but musical examples are thin on the ground (nonexistent?) so it might be a long haul to come up with something.
But this all sounds great to study. Thanks, Mike

On Wed, 2 Dec 2009, Stephen Tetley wrote:
As for the second half of what you get from a programming language, your system description frames what you want to do with an emphasis on dynamic aspects. This seems a good way off from the prior art in Haskell. For instance there are Haskell synthesizers - George Giorgidze's yampa-synth and Jerzy Karczmarczuk's Clarion (actually in Clean, but near enough). Here you build signal processing modules - unit generators, of course - Yampasynth uses arrows to do this Clarion uses infinite streams. With both you would build a synthesizer statically from unit generators and somehow run it to produce sounds[1].
Shameless advertisement here: http://hackage.haskell.org/package/synthesizer-core http://www.youtube.com/watch?v=KA6DE9jlpSY

On 02/12/09 01:55, Michael Mossey wrote:
I have a quite messy problem which is describable as a big state machine, at least in the way I think of it. An input "event" can trigger a cascade of changes to the state. Channel numbers must be assigned and tracked, table numbers as well, decisions about whether to create a new table or re-use an old one, global variables and commands added and/or modified, etc. So I am hoping for a comment from that perspective.
First, I wonder if some of the ideas in Functional Reactive Programming might help; its a very clean and declarative way of dealing with messy event-based stuff like this. Second, more generally, for Haskell design you need to take a step back and think about the mathematical relations between things in your domain that an application programmer cares about. Then you can think about how to map from your domain model to an implementation like CSound. Paul.

On Tue, Dec 1, 2009 at 8:01 PM, Michael P Mossey
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.
I have a problem that is very state-ful and I keep thinking of it as OO, which is driving me crazy. Haskell is several times harder to use than Python in this instance, probably because I'm doing it wrong.
To give you a larger context, this problem is essentially compiling a description of music (my own) into a kind of music-machine-language (CSound). CSound is relatively untidy.
In this one example, in a OO way of thinking, I have data called AssignedNumbers that assigns integers to unique strings and keeps track of the used integers and next available integer (the choice of available integer could follow a number of conventions so I wanted to hide that in an ADT.) So it has an associated function:
getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers)
What getNumber does is:
- check if the string already has a number assigned to it. If so, return that number.
- if not, pick the next available number.
- in all cases, return the possibly changed state of AssignedNumbers
Then in a larger data structure, it contains fields of type AssignedNumbers. Like
data MusicStuff = MusicStuff { oscillatorNumbers :: AssignedNumbers , tableNumbers :: AssignedNumbers , ... }
I'm using MusicStuff in a State monad, so I might write a function like
doSomeMusicStuff :: String -> String -> State MusicStuff (Int,Int) doSomeMusicStuff aString1 aString2 = do ms <- get (o1,newOscNums) = getNumber aString1 (oscillatorNumbers ms) (t1,newTabNums) = getNumber aString2 (tableNumbers ms) put ms { oscillatorNumbers = newOscNums , tableNumbers = newTabNums } return (o1,t1)
For what it does, this is extremely verbose and filled with distracting visual content. And this is just a very simple example---my real problem is several times more state-ful. Is there a better way?
As a quick observation, you might consider changing getNumber to be something like: nextNumber :: String -> NumberGroup -> State MusicStuff Int where NumberGroup is something like data NumberGroup = OscNums | TabNums |... nextNumber updates the appropriate set of numbers in MusicStuff and returns the number. doSomeMusicStuff then becomes: doSomeMusicStuff aString1 aString2 = (,) `liftM` nextNumber OscNums `ap` nextNumber TabNums or better yet (applicatively) doSomeMusicStuff aString1 aString2 = (,) <$> nextNumber OscNums <*> nextNumber TabNums

On Tue, Dec 1, 2009 at 9:01 PM, Robert Greayer
On Tue, Dec 1, 2009 at 8:01 PM, Michael P Mossey
wrote: Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.
I have a problem that is very state-ful and I keep thinking of it as OO, which is driving me crazy. Haskell is several times harder to use than Python in this instance, probably because I'm doing it wrong.
To give you a larger context, this problem is essentially compiling a description of music (my own) into a kind of music-machine-language (CSound). CSound is relatively untidy.
In this one example, in a OO way of thinking, I have data called AssignedNumbers that assigns integers to unique strings and keeps track of the used integers and next available integer (the choice of available integer could follow a number of conventions so I wanted to hide that in an ADT.) So it has an associated function:
getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers)
What getNumber does is:
- check if the string already has a number assigned to it. If so, return that number.
- if not, pick the next available number.
- in all cases, return the possibly changed state of AssignedNumbers
Then in a larger data structure, it contains fields of type AssignedNumbers. Like
data MusicStuff = MusicStuff { oscillatorNumbers :: AssignedNumbers , tableNumbers :: AssignedNumbers , ... }
I'm using MusicStuff in a State monad, so I might write a function like
doSomeMusicStuff :: String -> String -> State MusicStuff (Int,Int) doSomeMusicStuff aString1 aString2 = do ms <- get (o1,newOscNums) = getNumber aString1 (oscillatorNumbers ms) (t1,newTabNums) = getNumber aString2 (tableNumbers ms) put ms { oscillatorNumbers = newOscNums , tableNumbers = newTabNums } return (o1,t1)
For what it does, this is extremely verbose and filled with distracting visual content. And this is just a very simple example---my real problem is several times more state-ful. Is there a better way?
As a quick observation, you might consider changing getNumber to be something like:
nextNumber :: String -> NumberGroup -> State MusicStuff Int
where NumberGroup is something like
data NumberGroup = OscNums | TabNums |...
nextNumber updates the appropriate set of numbers in MusicStuff and returns the number. doSomeMusicStuff then becomes:
doSomeMusicStuff aString1 aString2 = (,) `liftM` nextNumber OscNums `ap` nextNumber TabNums
or better yet (applicatively)
doSomeMusicStuff aString1 aString2 = (,) <$> nextNumber OscNums <*> nextNumber TabNums
Oops, that's: doSomeMusicStuff aString1 aString2 = (,) `liftM` nextNumber aString1 OscNums `ap` nextNumber aString2 TabNums or: doSomeMusicStuff aString1 aString2 = (,) <$> nextNumber aString1 OscNums <*> nextNumber aString2 TabNums

Am Mittwoch 02 Dezember 2009 02:01:29 schrieb Michael P Mossey:
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.
I have a problem that is very state-ful and I keep thinking of it as OO, which is driving me crazy. Haskell is several times harder to use than Python in this instance, probably because I'm doing it wrong.
If you want to do something very stateful, it is a bit cumbersome in Haskell. Perhaps it is the wrong approach and you can do it with much less state. Or perhaps, this is possible, too, it is not a task for which Haskell is well suited. Or perhaps you're really doing it wrong because of lack of experience.
To give you a larger context, this problem is essentially compiling a description of music (my own) into a kind of music-machine-language (CSound). CSound is relatively untidy.
In this one example, in a OO way of thinking, I have data called AssignedNumbers that assigns integers to unique strings and keeps track of the used integers and next available integer (the choice of available integer could follow a number of conventions so I wanted to hide that in an ADT.) So it has an associated function:
getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers)
Yeah, that screams State Monad.
What getNumber does is:
- check if the string already has a number assigned to it. If so, return that number.
- if not, pick the next available number.
- in all cases, return the possibly changed state of AssignedNumbers
Then in a larger data structure, it contains fields of type AssignedNumbers. Like
data MusicStuff = MusicStuff { oscillatorNumbers :: AssignedNumbers , tableNumbers :: AssignedNumbers , ... }
I'm using MusicStuff in a State monad, so I might write a function like
doSomeMusicStuff :: String -> String -> State MusicStuff (Int,Int) doSomeMusicStuff aString1 aString2 = do ms <- get (o1,newOscNums) = getNumber aString1 (oscillatorNumbers ms) (t1,newTabNums) = getNumber aString2 (tableNumbers ms) put ms { oscillatorNumbers = newOscNums , tableNumbers = newTabNums } return (o1,t1)
For what it does, this is extremely verbose and filled with distracting visual content. And this is just a very simple example---my real problem is several times more state-ful. Is there a better way?
If you're doing that in many places, factor out the methods getOscillatorNumber :: String -> State MusicStuff Int getOscillatorNumber str = do ms <- get let on = oscilatorNumbers ms (o1,newOn) = getNumber str on put (ms{ oscillatorNumbers = newOn }) return o1 same for tableNumbers etc. Then doSomeMusicStuff aString1 aString2 = do o <- getOscillatorNumber aString1 t <- getTableNumber aString2 return (o,t) and the verbosity is moved to one place. That isn't worthwhile for seldomly used stuff, of course.
Note that in Python it would be a method
def doMusicStuff( self, s1, s2 ) : return (self.oscillatorNumbers.next(s1), self.oscillatorNumbers.next(s2))
Yeah, mutability gives brevity here.

Daniel Fischer wrote:
getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers)
Yeah, that screams State Monad.
Hi, thanks for all the advice. I was hoping my AssignedNumbers "class" would be useful with many data structures. In other words I would have data State1 = State1 { a :: AssignedNumbers, b :: AssignedNumbers, ... } data State2 = State2 { c :: AssignedNumbers, d :: AssignedNumbers, ... } func1 :: State State1 Int func1 = do ... something using a and b ... func2 :: State State2 Int func2 = do ... something using c and d ... So I thought maybe I could defined a function like nextNumber :: MonadState s m => (s -> AssignedNumbers) -> (AssignedNumbers -> s) -> m Int nextNumber retreive putBack = ... and have it be useful in both "State State1 a" and "State State2 a" monads, but defining the retrieve and putBack functions isn't pretty. I will try to grok Robert's reply also. Maybe he has something addressing this. Mike

Am Mittwoch 02 Dezember 2009 03:28:04 schrieb Michael Mossey:
Daniel Fischer wrote:
getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers)
Yeah, that screams State Monad.
Hi, thanks for all the advice.
I was hoping my AssignedNumbers "class" would be useful with many data structures. In other words I would have
data State1 = State1 { a :: AssignedNumbers, b :: AssignedNumbers, ... } data State2 = State2 { c :: AssignedNumbers, d :: AssignedNumbers, ... }
func1 :: State State1 Int func1 = do ... something using a and b ...
func2 :: State State2 Int func2 = do ... something using c and d ...
So I thought maybe I could defined a function like
nextNumber :: MonadState s m => (s -> AssignedNumbers) -> (AssignedNumbers -> s) -> m Int nextNumber retreive putBack = ...
and have it be useful in both "State State1 a" and "State State2 a" monads, but defining the retrieve and putBack functions isn't pretty.
I will try to grok Robert's reply also. Maybe he has something addressing this.
Definitely. data AssignType = Oscillator | Table | Thingamajig deriving (Eq, Ord, Ix) data MusicState = MS { assignedNumbers :: Array AssignType AssignedNumbers , other stuff } deriving (Everything you need) fetchNumber :: String -> AssignType -> State MusicState Int fetchNumber str ty = do an <- gets ((! ty) . assignedNumbers) let (i,newAn) = getNumber str an modify (\ms -> ms{ assignedNumbers = assignedNumbers ms // [(ty,newAn)] }) return i doSomeMusicStuff aString1 aString2 = do o <- fetchNumber aString1 Oscillator t <- fetchNumber aString2 Table return (o,t)
Mike

On Tue, Dec 1, 2009 at 7:01 PM, Michael P Mossey
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.
In this one example, in a OO way of thinking, I have data called AssignedNumbers that assigns integers to unique strings and keeps track of the used integers and next available integer (the choice of available integer could follow a number of conventions so I wanted to hide that in an ADT.) So it has an associated function:
What do the numbers and strings mean? Can you use an algebraic type instead of strings? Do particular numbers have meaning or are they just serial numbers? Can you compute some sort of checksum for the strings rather than rely on an external list of numbers? If you must have a list of numbers, can you embed it in a specialized string type, so that numbers get assigned as a side-effect of string construction? In other words, would it help to think more in terms of specific types rather than generic numbers and strings? -G

Michael P Mossey wrote:
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.
I have a problem that is very state-ful and I keep thinking of it as OO, which is driving me crazy. Haskell is several times harder to use than Python in this instance, probably because I'm doing it wrong.
Stop the presses! I had an idea to make this more functional in style. Do it through multiple passes. The idea is that we've got a list of musical events as input ("Node" is a term some algorithmic composers use, so I will use type Node.) In fact we could have other types of input data too, so I might need the algebraic type data InputType = Node ... | CSoundSource ... etc. Then we make a pass through the nodes using map concat to produce a bunch of Output data. data Output = OIStatement ... | OInstrName InstrName -- represents an instrument name -- (ultimately we need a number, but -- won't know that # during first -- pass) | OInstrNum Int -- when we compute an instrument -- number, this will replace the above | OMixer MixerName ... we have a function processInput: processInput :: InputType -> [Output] This expresses the idea that a single input may result in the generation of several pieces of output data. The first pass is just a concat map firstPass :: [InputType] -> [Output] firstPass = concatMap processInput In translating an InputType datum, we look at it "in isolation"---here it sits in front of us in the stream, and we haven't maintained a lot of state---and we translate it to some intermediate Output form, making all specific calculations or substitutions possible at that given time and context. Then further passes are needed, many of which are folds. For example, to assign the instrument number I have some kind of NumberDatabase, but now my dealings with it are limited to a single fold. assignNumbers :: [Output] -> NumberDatabase assignNumbers outputList = foldl g newNumberDatabase outputList where g outputDatum numberDb = case outputDatum of OInstrName n -> ... ah! unassigned name! update db _ -> numberDb -- just return unchanged All the rest of the processing can be done via filters, folds, and maps. Does this seem more functional in style? Thanks, Mike

Michael P Mossey schrieb:
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.
I have a problem that is very state-ful and I keep thinking of it as OO, which is driving me crazy. Haskell is several times harder to use than Python in this instance, probably because I'm doing it wrong.
To give you a larger context, this problem is essentially compiling a description of music (my own) into a kind of music-machine-language (CSound). CSound is relatively untidy.
There are currently two public interfaces to CSound: http://hackage.haskell.org/packages/archive/haskore/0.1/doc/html/Haskore-Int... http://hackage.haskell.org/package/hCsound You may also want to use SuperCollider: http://hackage.haskell.org/package/hsc3
participants (9)
-
Casey Hawthorne
-
Daniel Fischer
-
Gregg Reynolds
-
Henning Thielemann
-
Michael Mossey
-
Michael P Mossey
-
Paul Johnson
-
Robert Greayer
-
Stephen Tetley