[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