[Haskell-cafe] seems like I'm on the wrong track

Michael P Mossey mpm at alumni.caltech.edu
Tue Dec 1 20:01:29 EST 2009

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 

   - 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))

More information about the Haskell-Cafe mailing list