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. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe