<br><br><div class="gmail_quote">On Tue, Dec 1, 2009 at 9:01 PM, Robert Greayer <span dir="ltr"><<a href="mailto:robgreayer@gmail.com">robgreayer@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br><br><div class="gmail_quote"><div class="im">On Tue, Dec 1, 2009 at 8:01 PM, Michael P Mossey <span dir="ltr"><<a href="mailto:mpm@alumni.caltech.edu" target="_blank">mpm@alumni.caltech.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Perhaps someone could either (1) help me do what I'm trying to do, or (2) show me a better way.<br>
<br>
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.<br>
<br>
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.<br>
<br>
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:<br>
<br>
getNumber :: String -> AssignedNumbers -> (Int,AssignedNumbers)<br>
<br>
What getNumber does is:<br>
<br>
- check if the string already has a number assigned to it. If so, return that number.<br>
<br>
- if not, pick the next available number.<br>
<br>
- in all cases, return the possibly changed state of AssignedNumbers<br>
<br>
Then in a larger data structure, it contains fields of type AssignedNumbers. Like<br>
<br>
data MusicStuff = MusicStuff<br>
{ oscillatorNumbers :: AssignedNumbers<br>
, tableNumbers :: AssignedNumbers<br>
, ... }<br>
<br>
I'm using MusicStuff in a State monad, so I might write a function like<br>
<br>
doSomeMusicStuff :: String -> String -> State MusicStuff (Int,Int)<br>
doSomeMusicStuff aString1 aString2 = do<br>
ms <- get<br>
(o1,newOscNums) = getNumber aString1 (oscillatorNumbers ms)<br>
(t1,newTabNums) = getNumber aString2 (tableNumbers ms)<br>
put ms { oscillatorNumbers = newOscNums<br>
, tableNumbers = newTabNums }<br>
return (o1,t1)<br>
<br>
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?<br></blockquote></div>
<div>
<br>As a quick observation, you might consider changing getNumber to be something like:<br><br>nextNumber :: String -> NumberGroup -> State MusicStuff Int<br><br>where NumberGroup is something like <br><br>data NumberGroup = OscNums | TabNums |...<br>
<br>nextNumber updates the appropriate set of numbers in MusicStuff and returns the number. doSomeMusicStuff then becomes:<br><br>doSomeMusicStuff aString1 aString2 = (,) `liftM` nextNumber OscNums `ap` nextNumber TabNums<br>
<br>or better yet (applicatively)<br><br>doSomeMusicStuff aString1 aString2 = (,) <$> nextNumber OscNums <*> nextNumber TabNums<br>
<br></div></div></blockquote><div><br>Oops, that's:<br><br>doSomeMusicStuff aString1 aString2 = <br> (,) `liftM` nextNumber aString1 OscNums `ap` nextNumber aString2 TabNums<br>
<br>or:<br><br>doSomeMusicStuff aString1 aString2 = <br> (,) <$> nextNumber aString1 OscNums <*> nextNumber aString2 TabNums<br> </div></div><br>