[Haskell-cafe] Lens, with ability to create a data-field when it's missing

Takayuki Muranushi muranushi at gmail.com
Thu Jan 3 10:48:07 CET 2013


Dear All, I really am enjoying the lens (it is tough to learn, though :)

Recently, I've been trying to implement a dynamic object --- a
collection of methods that you can update at run-time --- using lens
[1][2][3]. After several attempts, I think I have located the center
of my problem:

Lens with the ability "to create a data-field when it's missing." My
question: is it possible?

There are many excellent examples of partial lenses in the lens
library, such as '_head' from Data.List.Lens 'dynamic' from
Data.Dynamic.Lens . To me, they seem to share the following set of
common behavior (allow me to use inaccurate terms...)

- set l a s : if the field is present, insert 'a'; otherwise, do nothing.
- over l f s : if the field is present, map 'f' over it. otherwise, do nothing.
- preview l s : if the field is present, return 'Just a'. otherwise,
return 'Nothing' .

Instead, I want the following set of behaviors:

- set l a s : if the field is present, insert 'a'; otherwise, *create
the field* and insert 'a'.
- over l f s : if the field is present, map 'f' over it. otherwise, do nothing.
- preview l s : if the field is present, return 'Just a'. otherwise,
return 'Nothing' .

For example, the current behavior of _head is
    >>> [] & _head .~ 1
    []
I want to implement a variant _head' , such that
    >>> [] & _head' .~ 1
    [1]


Let us call this behavior 'Member' for the moment.

I have a implementation of 'Member' [4][5] but they are
unsatisfactory. [4] involves runtime errors and breaking of lens laws.
[5] shows that we can "create a field" only if we treat Dynamic
explicitly out of lens context.

I don't know how 'Member' will fit in the lens hierarchy
http://i.imgur.com/FgfVW.png or even if it fits at all.
Member is weaker than Getter and probably is a Fold since you have
only partial getting (^?) for Member. Member is weaker than Prism
since you cannot construct a whole Object from just one Member. On the
other hand, setter side of Member requires (s -> b -> t) interface of
a Lens, because the setter need to update the whole Object when the
field under concern is missing.

That said, let me put this question in another way;

" We can construct a (Simple Lens s a) from (getter :: s -> a) and
(setter :: s -> a -> s), and we can construct a (Getter s a) from
(getter :: s -> a).
  Then why we cannot construct a (Simple Setter s a) from (setter :: s
-> a -> s) ? "

Does Member deserve a new node in The Lens Hierarchy tree? Or can we
implement it by combinations of existing prisms, folds etc? Or does it
fall outside of the lens framework?

I appreciate any comments.
Takayuki

[1] https://github.com/nushio3/practice/tree/master/duck
[2] http://d.hatena.ne.jp/nushio/20121226#p2 (Japanese)
[3] http://hackage.haskell.org/packages/archive/dynamic-object/0.1.0.1/doc/html/Data-Object-Dynamic-Types.html
[4] https://github.com/nushio3/practice/blob/master/lens/newfield.hs
[5] https://github.com/nushio3/practice/blob/master/lens/object-4.hs


--
Takayuki MURANUSHI
The Hakubi Center for Advanced Research, Kyoto University
http://www.hakubi.kyoto-u.ac.jp/02_mem/h22/muranushi.html



More information about the Haskell-Cafe mailing list