
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