
I'm playing with functional references and looking for some feedback on a small FRec library I put together: http://www.thenewsh.com/~newsham/FRef.hs Novel (I think) is that the library is applied to some data accesses that are not normally covered by functional references -- ie. extracting words or replacing words in a string or values in an association list. I'm hoping it will provides a useful framework for editing complex values such as data embedded in Base64 cookies in an HTTP header. Tim Newsham http://www.thenewsh.com/~newsham/

Nice. I've written similar stuff a couple of times before, but the formulation using Maybe and modify definitely solves some problems I started to notice as I used it on bigger structures. However, it might be better to separate a class of "never failing" references, where the reader is guaranteed to succeed, from "potentially failing" references which give a Maybe value. I'd also not use the names "get" and "modify" because they are already used by MonadState. I always used "frGet", "frSet", and "frModify", and then tended to not use them directly as I was generally working in a state monad. Here's a few more primitives that I found quite useful:
fetch :: MonadState s m => FRef s a -> m (Maybe a) fetch ref = liftM (frGet ref) get
(=:) :: MonadState s m => FRef s a -> a -> m () r =: v = modify (frSet r v)
($=) :: MonadState s m => FRef s a -> (a -> a) -> m () r $= f = modify (frModify r f)
You should package this up and put it on hackage.
-- ryan
On Thu, Sep 4, 2008 at 4:51 PM, Tim Newsham
I'm playing with functional references and looking for some feedback on a small FRec library I put together:
http://www.thenewsh.com/~newsham/FRef.hs
Novel (I think) is that the library is applied to some data accesses that are not normally covered by functional references -- ie. extracting words or replacing words in a string or values in an association list. I'm hoping it will provides a useful framework for editing complex values such as data embedded in Base64 cookies in an HTTP header.
Tim Newsham http://www.thenewsh.com/~newsham/ _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

You should package this up and put it on hackage.
It is nice, but there is already another FRef package on hackage (Data.Accessor) and I have a home-grown one of my own, which uses different notation / combinators to either the hackage one or Tim's. There are also fragments of FRef-like things in some of the big libraries like OpenGL and GTK. I think it would be worth spending some time (on this mailing list, perhaps, or in another forum) trying to hash out a decent API which meets most people's requirements, rather than ending up with 4 or 5 slightly different ones. Jules

I think it would be worth spending some time (on this mailing list, perhaps, or in another forum) trying to hash out a decent API which meets most people's requirements, rather than ending up with 4 or 5 slightly different ones.
Indeed. I have my own version here: http://code.haskell.org/yi/Yi/Accessor.hs I'd rather use a standard package, but I could not contact the author of the data-accessor package to join efforts. Cheers -- JP

I think it would be worth spending some time (on this mailing list, perhaps, or in another forum) trying to hash out a decent API which meets most people's requirements, rather than ending up with 4 or 5 slightly different ones.
Indeed. I have my own version here:
http://code.haskell.org/yi/Yi/Accessor.hs
I'd rather use a standard package, but I could not contact the author of
Jean-Philippe Bernardy wrote: the
data-accessor package to join efforts.
I too have a home-rolled version nearly identical to this one. The only real difference is using a (whole -> part -> whole) modifier instead of ((part -> part) -> whole -> whole) in the dictionary type. That decision was salient for my particular uses, but on the whole I like the Yi.Accessor approach better. For an official API, I think a (setter = modifier . const) function would be helpful for brevity and clarity. The other difference, in terms of API, is I was using names "theX" and "resetX" rather than "getter" and "modifier" (I also have a "setX" which requires a class declaring an emptyX value for the whole type). I'm not too invested in my particular names, but I think having something short which isn't too evocative of the StateMonad is important. The reason I think it shouldn't be too evocative of State is that the functions are pure and keeping their names distinct gives a good mnemonic to remember which ones are State-ful and which ones are pure. Tim Newsham's approach with invertible functions is interesting, though it feels like it's another layer wrapped on top of the primitive idea of functional references. My code also had an extra layer lifting the explicit dictionaries into type class dictionaries. This was helpful for writing functions which are polymorphic over the state type, though it suffers from the limitation that you can only have a single accessor for each part type in a given whole type. -- Live well, ~wren

Tim Newsham's approach with invertible functions is interesting, though it feels like it's another layer wrapped on top of the primitive idea of functional references.
Not all of the refs are using invertible functions.. however, the ones that are invertible are more flexible.. you can use them to make functional references that are mapped over lists, for example. I've reformulated my code a few times since initially posting it.. In the latest incarnation, FRefGen (generic FRefs with arbitrary get/modify) and Inv (invertible functions) are both instances of an FRef class. In earlier versions I had a function for converting an invertible into an FRef.
~wren
Tim Newsham http://www.thenewsh.com/~newsham/

On Fri, 5 Sep 2008, Jean-Philippe Bernardy wrote:
I think it would be worth spending some time (on this mailing list, perhaps, or in another forum) trying to hash out a decent API which meets most people's requirements, rather than ending up with 4 or 5 slightly different ones.
Indeed. I have my own version here:
http://code.haskell.org/yi/Yi/Accessor.hs
I'd rather use a standard package, but I could not contact the author of the data-accessor package to join efforts.
I had no problem contacting Luke Palmer and I have recently added my stuff to the package. See also http://www.haskell.org/haskellwiki/Record_access You may add the other existing packages for reference.

On Fri, 5 Sep 2008, Jules Bean wrote:
I think it would be worth spending some time (on this mailing list, perhaps, or in another forum) trying to hash out a decent API which meets most people's requirements, rather than ending up with 4 or 5 slightly different ones.
This sounds like a good plan, but please make sure the result is as free as GHC, rather than GPL like data-accessor is. It's so simple that it being GPL just drives people for whom licencing is an issue to write an alternative rather than consider complying. Ganesh

I've discussed the license of data-accessor with it's authors (Luke Palmer & Henning Thieleman). They are ok with changing it to BSD3. So I don't think the license will be a reason not to use it. Tim -----Original Message----- From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Ganesh Sittampalam Sent: Saturday, 6 September 2008 4:52 AM To: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Functional references On Fri, 5 Sep 2008, Jules Bean wrote:
I think it would be worth spending some time (on this mailing list, perhaps, or in another forum) trying to hash out a decent API which meets most people's requirements, rather than ending up with 4 or 5 slightly different ones.
This sounds like a good plan, but please make sure the result is as free as GHC, rather than GPL like data-accessor is. It's so simple that it being GPL just drives people for whom licencing is an issue to write an alternative rather than consider complying. Ganesh _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Thu, 4 Sep 2008, Ryan Ingram wrote:
Nice. I've written similar stuff a couple of times before, but the formulation using Maybe and modify definitely solves some problems I started to notice as I used it on bigger structures. However, it might be better to separate a class of "never failing" references, where the reader is guaranteed to succeed, from "potentially failing" references which give a Maybe value.
I'd also not use the names "get" and "modify" because they are already used by MonadState. I always used "frGet", "frSet", and "frModify", and then tended to not use them directly as I was generally working in a state monad.
Haskell already supports qualification, why manual prefixing?

On Fri, Sep 5, 2008 at 1:39 PM, Henning Thielemann
Haskell already supports qualification, why manual prefixing?
This is just a stylistic opinion, but I absolutely hate "required" qualifications; it is a waste of typing and, in my opinion, it makes the resulting code look more cluttered and harder to read. It's especially bad when modules are extremely likely to be used together, like Control.Monad.State & FRef, or Data.Map & the Prelude. You end up being required to import one or the other qualified. I direct you to my proposal for ad-hoc overloading, recently discussed on this list, as a way to solve this problem. In my experience, the code is almost always unambiguous without the qualification because using the "wrong" operator would fail to typecheck. In this case, I agree that manual prefixing isn't really better, but using ugly names encourages people to find better ones. I couldn't think of any off the top of my head, but I wasn't trying very hard. -- ryan

It's especially bad when modules are extremely likely to be used together, like Control.Monad.State & FRef, or Data.Map & the Prelude. You end up being required to import one or the other qualified.
I think in the case of State vs. FRef a simple solution is to make two modules: FRef, which uses "get" and "set" and "modify" naturally, and FRef.State which defines State equivalents without polluting the namespace. Then if you're working with pure functions you can import FRef and use the natural names, and when you're using the State monad you can import FRef.State and get the State definitions that dont interfere with the standard "get" and "modify" names. In the rare case (I think, am I wrong?) where you use both State and FRef "modify" and "get" definitions in the same file, you can import the one you use less off qualified...
-- ryan
Tim Newsham http://www.thenewsh.com/~newsham/
participants (8)
-
Ganesh Sittampalam
-
Henning Thielemann
-
Jean-Philippe Bernardy
-
Jules Bean
-
Ryan Ingram
-
Tim Docker
-
Tim Newsham
-
wren ng thornton