[Haskell-cafe] seems like I'm on the wrong track
Robert Greayer
robgreayer at gmail.com
Tue Dec 1 21:03:05 EST 2009
On Tue, Dec 1, 2009 at 9:01 PM, Robert Greayer <robgreayer at gmail.com> wrote:
>
>
> On Tue, Dec 1, 2009 at 8:01 PM, Michael P Mossey <mpm at alumni.caltech.edu>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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20091201/17e003aa/attachment.html
More information about the Haskell-Cafe
mailing list