[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