On Jul25, apfelmus wrote:
> The point is to be
> able to define both  zip  and  pairs  with one and the same operator :< .

There's actually a quite simple way of doing this.  You make the view
type polymorphic, but not in the way you did:

   type Queue elt
   empty :: Queue elt
   cons :: elt -> Queue elt -> Queue elt

   data ViewL elt rec = EmptyL
                      | elt :< rec

   view :: Queue elt -> ViewL elt (Queue elt)
   view2 :: Queue elt -> ViewL elt (ViewL elt (Queue elt))

That is, the result of the view type is a parameter, so you can
instantiate it with both the viewed type and another view (and so on if
you want more levels).

Then the client code looks like this:

myzip :: Queue a -> Queue b -> Queue (a,b)
myzip a b = case (view a, view b) of 
              (EmptyL, _) -> empty
              (_, EmptyL) -> empty
              (h1 :< t1, h2 :< t2) -> (h1,h2) `cons` myzip a b

pairs :: Queue a -> Queue (a,a)
pairs a = case view2 a of
            h1 :< (h2 :< t) -> (h1, h2) `cons` pairs t 
            _ -> empty

The only difference with view patterns is that you can do the view2
inside the pattern itself:

pairs (view2 -> h1 :< (h2 :< t)) = (h1,h2) `cons` pairs t
pairs _                          = empty

This would be useful if the thing you were viewing were deep inside
another pattern.

This is a well-known technique in the ML community; see, e.g., 
http://www.cs.cmu.edu/~tom7/papers/wizard.pdf

-Dan
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to