[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



More information about the Haskell-Cafe mailing list