{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FunctionalDependencies #-} import Data.Vector (Vector, fromList, toList) -- View0 works at the element level, converting -- individual values to their abstract representations -- E.g.: ByteString -> String class View0 a where type ViewRep0 a view0 :: a -> ViewRep0 a -- View1 works at the functor level -- E.g.: Vec -> Seq class (Functor f, Functor (ViewRep1 f)) => View1 f where type ViewRep1 f :: * -> * view1 :: f a -> ViewRep1 f a -- A functor's View1 applied to an element yields the -- functor's View0 instance View1 f => View0 (f a) where type ViewRep0 (f a) = ViewRep1 f a view0 :: f a -> ViewRep0 (f a) view0 = view1 class DeepView a b | a -> b where deepView :: a -> b instance {-# OVERLAPPABLE #-} (View0 a, b ~ ViewRep0 a) => DeepView a b where deepView :: a -> b deepView = view0 -- On a functor level, DeepView first applies DeepView recursively -- to the underlying elements, then it applies View1 to the functor itself instance {-# OVERLAPPING #-} (View1 f, DeepView a b, c ~ ViewRep1 f b) => DeepView (f a) c where deepView = view1 . fmap deepView -- Example data ImplType = ImplType data AbstractType = AbstractType instance View0 ImplType where type ViewRep0 ImplType = AbstractType view0 :: ImplType -> AbstractType view0 _ = AbstractType instance View1 Vector where type ViewRep1 Vector = [] view1 :: Vector a -> [a] view1 = toList main = do let v :: Vector (Vector ImplType) = fromList [fromList [ImplType, ImplType]] let v0 :: [Vector ImplType] = view0 v let v1 :: Vector[ImplType] = fmap view0 v let v1' :: [[ImplType]] = view0 $ fmap view0 v let v1 :: [[AbstractType]] = deepView v return ()