# [Haskell-cafe] Re: is there a more concise way to generate helper functions for a datatype built on records?

apfelmus 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
>
> wouldn't
> 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)
= (a,a')

but that's impossible when a is different from a'.

Regards,
apfelmus

```