On Jul25, apfelmus wrote: > Dan Licata wrote: > > There's actually a quite simple way of doing this. You make the view > > type polymorphic, but not in the way you did: > > > > 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. > > Well, the main feature of view patterns is that you can nest them. In > other words, the canonical way of writing pairs would be > > pairs (view -> h1 :< (view -> h2 :< t)) = (h1,h2) `cons` pairs t > pairs _ = empty > > Nesting means to decide "later" on how to pattern match the nested part. > With view2, you have to make this decision before, something I want to > avoid. > > For example, take the (silly) definition > > foo :: Queue a -> Queue a > foo xs = case view xs of > x :< (y :< zs) -> x `cons` zs > x :< ys -> ys > EmptyL -> empty > > Here, ys is a Queue and (y :< zs) is a ViewL. By scrutinizing xs > via view , both have to be a Queue. By scrutinizing it via view2 , > both have to be a ViewL. But I want to mix them. > > The idea is to introduce a new language extension, namely the ability to > pattern match a polymorphic type. For demonstration, let > > class ViewInt a where > view :: Integer -> a > > instance ViewInt [Bool] where > view n = ... -- binary representation > > data Nat = Zero | Succ Nat > > instance ViewInt Nat where > view n = ... -- representation as peano number > > be some views of the integers. Now, I'd like to be able to write > > bar :: (forall a . ViewInt a => a) -> String > bar Zero = ... > bar (True:xs) = ...
This doesn't make sense to me: Zero :: Nat and therefore Zero :: ViewInt Nat => Nat but you can't generalize from that to Zero :: forall a. ViewInt a => a E.g., Zero does not have type ViewInt [Bool] => Bool Maybe you wanted an existential instead, and what you're writing is sugar for bar :: (exists a . ViewInt a => a) -> String bar (pack[Nat](view[Nat] -> Zero)) = ... bar (pack[Bool List](view[Bool List] -> True:xs)) = ... (where I'm using [] to make the polymorphic instantiations clear). That is, you open the existential, and then use the view function at the the unpacked type in each case and match against the result. Note that matching against types like this is a form of intensional type analysis. -Dan _______________________________________________ Haskell-Cafe mailing list [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
