[Haskell-cafe] use of modules to save typing
Job Vranish
job.vranish at gmail.com
Thu Jul 8 10:11:41 EDT 2010
For working with record fields inside of state monads I would recommend
trying out one of these packages:
lenses
fclabels
data-accessor
(I think I'm forgetting a couple)
They all have special mechanisms for working with record fields inside state
monads (and have lots of other cool stuff)
I'm partial to lenses (I wrote it :) ), but the others are quite good as
well.
Hmmm I just noticed that hackage is not generating the documentation for
latest version of lenses. I shall have to find out why.
In the meantime, the documentation for the 0.1.2 version is essentially the
same.
- Job
On Thu, Jul 8, 2010 at 4:08 AM, Michael Mossey <mpm at alumni.caltech.edu>wrote:
> I'm fairly beginnerish to Haskell, and come from OO. I have a complaint
> about Haskell, but I think I found a good solution. Any suggestions welcome.
>
> I have RSI and like to minimize typing. The use of classes as name spaces
> helps to do that. Also I can use some Emacs abbreviation magic easily with
> OO and not so easily with Haskell. I'll explain in a second.
>
> In Haskell, when defining data for complex programs I like to use named
> fields to allow for changing data definitions without having to change all
> code. But named fields are top-level functions (I think). They must be
> chosen not to clash.
>
> My habit has been to prefix them with the name of the constructor. So in a
> program for playing back musical documents that needs to track some state,
> we have:
>
> data PlayState = PlayState
> { playState_cursor :: Int
> , playState_verts :: [Loc]
> , playState_len :: Int
> , playState_doc :: MusDoc
> }
>
> Note all these "playState_" prefixes. Lots of typing, which is not good.
>
> In OO, you could type
>
> x.cursor()
>
> In Haskell you have to type
>
> playState_cursor x
>
> which also, I feel, is harder to read.
>
> Now suppose I want to use PlayState with a State monad.
>
> -- Increment the cursor.
> incrCursor :: State PlayState ()
> incrCursor =
> cur <- gets playState_cursor
> len <- gets playState_len
> let newCur = min (cur+1) (len-1)
> p <- get
> put $ p {playState_cursor = newCur}
>
> Okay, I'm sorry, that is just a lot of typing for what it is doing. Not
> good for people with RSI, and not all that readable.
>
> I could define a function to make modifying the state a little easier.
>
> playState_update_cursor :: Int -> PlayState -> PlayState
> playState_update_cursor i p = p {playState_cur=i}
>
> Then incrCursor would look like:
>
> incrCursor :: State PlayState ()
> incrCursor =
> cur <- gets playState_cursor
> len <- gets playState_len
> let newCur = min (cur+1) (len-1)
> modify (playState_update_cursor newCur)
>
> Notice how often the characters "playState_" get typed. This would be a
> great situation for Emacs abbreviations. When you define an abbreviation in
> Emacs, such as defining "xps" to expand to "PlayState", emacs will watch for
> the characters xps. It will then replace "xps" with "PlayState" when you
> type a non-alphanumeric character following "xps". So if I type "xps." the
> moment I hit "." it changes to "PlayState."
>
> But I would have a hard time using this feature with "playState_" because
> it is always followed by an alphanumeric character.
>
> So my idea, now, is to put the definition of PlayState in its own module
> and import it qualified as PlayState.
>
> ---------------- module PlayState --------------
>
> data PlayState = PlayState
> { cursor :: Int
> , verts :: [Loc]
> , len :: [Int]
> , doc :: MusDoc
> }
>
> update_cursor i p = p {cursor = i}
>
> -----------------------------------------------
>
> I got rid of the "playState_" prefixes because I am not worried about using
> generic field names like "doc". They won't clash if I always import this
> qualified. And that reduces the necessary typing in the definition.
>
> Now my monad looks like
>
> testMonad = do
> cursor <- gets PlayState.cursor
> len <- gets PlayState.len
> let newCur = min (cur+1) (len-1)
> modify $ PlayState.update_cursor newCur
>
> Now I can define an abbreviation for PlayState. This is a big help. Also, I
> find this more readable. To me
>
> PlayState.cursor
>
> is more readable than
> playState_cursor
>
> For one thing, syntax highlighting helps in the former case. For another,
> the latter case requires that you recognize a naming convention, but the
> former case says clearly: "cursor is within the namespace PlayState, so this
> combination must be describing a cursor related to PlayState."
>
>
>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20100708/0ac92c79/attachment.html
More information about the Haskell-Cafe
mailing list