{-# 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 ()