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

Isaac Dupree isaacdupree at charter.net
Tue Nov 27 14:33:50 EST 2007


apfelmus wrote:
> Benedikt Huber wrote:
>>  > type Upd a = a -> a
>>  > data Ref cx t
>>  > = Ref { select :: cx -> t , update :: Upd t -> Upd cx }
> 
> Functional references are also called "lens", I'm going to use that term 
> from now on.
> 
> As a minor note, I somehow prefer a single primitive
> 
>   data Lens s a = Lens { focus :: s -> (a, a -> s) }

nice name.


> there cannot be 
> a general parallel combinator
> 
>   (&&&) :: Lens a b -> Lens a c -> Lens a (b,c)
> 
> with for example
> 
>   players = player1 &&& player2
> 
> That's because the two arguments might not be parallel at all. For 
> instance, consider
> 
>   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
?

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...

Isaac


More information about the Haskell-Cafe mailing list