Is there a simple existing library that provides views of data types in terms of unit, product and sum?<br><br>Here's what I threw together for my own use. I used associated types, though functional dependencies would work as well.<br>
<br><span style="font-family: courier new,monospace;"> class HasView t where</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> type View t</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> view :: t -> View t</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> unview :: View t -> t</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> -- View instances</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> instance HasView (Maybe a) where</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> type View (Maybe a) = Either () a</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> view Nothing = (Left ())</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> view (Just a) = (Right a)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> unview (Left ()) = Nothing</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> unview (Right a) = (Just a)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> instance HasView [a] where</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> type View [a] = Either () (a,[a])</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> view [] = (Left ())</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> view (a:as) = (Right (a,as))</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> unview (Left ()) = []</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> unview (Right (a,as)) = (a:as)</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> onView2 :: (HasView a, HasView b, HasView c) =></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (View a -> View b -> View c)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> -> (a -> b -> c)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> onView2 op a b = unview (view a `op` view b)</span><br style="font-family: courier new,monospace;">
<br>Thanks, - Conal<br>