[Haskell-cafe] Re: is there a more concise way to generate helper
functions for a datatype built on records?
apfelmus at quantentunnel.de
Tue Nov 27 15:55:00 EST 2007
Isaac Dupree wrote:
> apfelmus wrote:
>> dup :: Lens a (a,a)
>> dup = id &&& id
>> Which component of the pair should
>> put dup :: a -> (a,a) -> (a,a)
>> change? The first, the second, or even both?
>> put :: Lens s a -> a -> s -> s
>> put x = flip $ snd . focus x
> put dup :: (a,a) -> a -> a
Oops, of course.
> Arrows IIRC resolve this dilemma by arbitrarily saying the first
> argument of (&&&) takes effect first... a solution I'm not entirely
> happy with. Here, first it would put the first element of the pair,
> then it would put the second, so the result would be the second element.
> If it were 2d vectors, x::Lens Vector Double, angle::Lens Vector Angle,
> it makes a difference whether x-coordinate or angle is changed first,
> and again, (&&&) could sequence.
> I wish there was some way to compose them that guaranteed
> order-independence, and didn't work otherwise, though. I suppose
> QuickCheck could be used to catch most
> parallel/disjoint-assumption-mistakes like that...
The situation is much worse, even dropping order-independence doesn't
help: the lens laws
get x (put x a s) = a
put x (get x s) s = s
are already violated for dup ! Assuming that
get dup :: a -> (a,a)
is total (i.e. first and second component not undefined ), parametric
polymorphism dictates that it can only be
get dup = \a -> (a,a)
Now, we should have
get dup x (put dup (a,a') s)
= (put dup (a,a') s, put dup (a,a') s)
but that's impossible when a is different from a'.
More information about the Haskell-Cafe