[Haskell-beginners] making translation from imperative code

Magnus Therning magnus at therning.org
Tue Mar 31 09:04:09 EDT 2009


On Tue, Mar 31, 2009 at 1:54 PM, Michael Mossey <mpm at alumni.caltech.edu> wrote:
> I'm translating a Python program into Haskell, and running into a
> problem---a type of code where I don't know how to make the conceptual
> shift.
>
> The Python code does a graphical layout of a music score. There is a loop in
> which it add items (chords, symbols, text, etc.) one at a time, moving to
> the right, until it reaches the end of the line. So in typical imperative
> code, we have a bunch of loop state, such as
>
>   - xpos of last chord or symbol placed
>   - time of last chord or symbol placed
>   - several StaffData objects, each containing the symbols that went
>     on that particular staff
>   - a cache of miscellaneous information about each symbol for later
>     reference
>
> So imperative code is pretty simple: loop, and each time update the state.
> Much of this state consists of lists  to which symbols are added once per
> loop.
>
> I'm not sure how to conceive of this problem in Haskell. Without using
> mutable variables, I would have to "rebuild" the state on each loop. I can
> do that, but I don't want to see an ugly proliferation of variables.
>
> I would like to encapsulate the state in a single object so I can pass it
> around as a single variable, like
>
> LoopState = LoopState {
>     lastXPos :: Int,
>     lastTime :: Double,
>     staffDataLists :: [ ( String, StaffData ) ],
>     chunkCache :: [ ( Double, Chunk ) ]
>     }
>
> So lets say I have an instance of this call x. Let's say I want to create y,
> by "updating" lastXPos. Do I have to do something like this:
>
> newLastXPos = 25
> y = LoopState ( newLastXPos, lastTime x, staffDataLists x,
>                chunkCache x )
>
> Obviously this is verbose compared to an imperative language in which one
> would say:
> newLastPos = 25
> x.setLastXPos( newLastXPos )
>
> I am aware that Haskell provides some mutable structures, but part of what
> drew me to Haskell was the benefit of avoiding mutable data (reducing bugs
> and making it easier to reason about my program's behavior). Are there any
> shortcuts for doing things like the above?

Have you considered the sort of named updates like the following?

  data Foo = Foo { i :: Int, j :: Int } deriving (Show)

Loading that into ghci you can do things like this:

*Foo> let f = Foo 25 25
*Foo> f
Foo {i = 25, j = 25}
*Foo> f { i = 35 }
Foo {i = 35, j = 25}

That might be more to your liking.

/M

-- 
Magnus Therning                        (OpenPGP: 0xAB4DFBA4)
magnus@therning.org          Jabber: magnus@therning.org
http://therning.org/magnus         identi.ca|twitter: magthe


More information about the Beginners mailing list