reorganized examples directory
[coq-hetmet.git] / examples / BiGArrow.hs
diff --git a/examples/BiGArrow.hs b/examples/BiGArrow.hs
new file mode 100644 (file)
index 0000000..466fbc2
--- /dev/null
@@ -0,0 +1,100 @@
+{-# OPTIONS_GHC -XModalTypes -XMultiParamTypeClasses -ddump-types -XNoMonoPatBinds -XFlexibleInstances -XGADTs -XUndecidableInstances #-}
+module BiGArrow
+where
+import GHC.HetMet.GArrow
+import Control.Category
+import Control.Arrow
+import Prelude hiding ( id, (.) )
+
+
+
+--------------------------------------------------------------------------------
+-- BiGArrows
+
+class GArrow g (**) u => BiGArrow g (**) u where
+  -- Note that we trust the user's pair of functions actually are
+  -- mutually inverse; confirming this in the type system would
+  -- require very powerful dependent types (such as Coq's).  However,
+  -- the consequences of failure here are much more mild than failures
+  -- in BiArrow.inv: if the functions below are not mutually inverse,
+  -- the LoggingBiGArrow will simply compute the wrong result rather
+  -- than fail in some manner outside the language's semantics.
+  biga_arr :: (x -> y) -> (y -> x) -> g x y
+  biga_inv :: g x y -> g y x
+
+
+
+
+--------------------------------------------------------------------------------
+-- GArrow-pairs are BiGArrows (but not a GArrowDrop!)
+
+-- For any GArrow instance, its mutually inverse pairs form a BiGArrow
+data GArrow g (**) u => GArrowInversePair g (**) u x y =
+    GArrowInversePair { forward :: g x y , backward :: g y x }
+instance GArrow g (**) u => Category (GArrowInversePair g (**) u) where
+  id    = GArrowInversePair { forward = id , backward = id }
+  f . g = GArrowInversePair { forward = (forward f) . (forward g) , backward = (backward g) . (backward f) }
+instance GArrow g (**) u => GArrow (GArrowInversePair g (**) u) (**) u where
+  ga_first     f = GArrowInversePair { forward = ga_first  (forward f), backward = ga_first  (backward f) }
+  ga_second    f = GArrowInversePair { forward = ga_second (forward f), backward = ga_second (backward f) }
+  ga_cancell     = GArrowInversePair { forward = ga_cancell           , backward = ga_uncancell }
+  ga_cancelr     = GArrowInversePair { forward = ga_cancelr           , backward = ga_uncancelr }
+  ga_uncancell   = GArrowInversePair { forward = ga_uncancell         , backward = ga_cancell   }
+  ga_uncancelr   = GArrowInversePair { forward = ga_uncancelr         , backward = ga_cancelr   }
+  ga_assoc       = GArrowInversePair { forward = ga_assoc             , backward = ga_unassoc   }
+  ga_unassoc     = GArrowInversePair { forward = ga_unassoc           , backward = ga_assoc     }
+instance GArrowSwap g (**) u => GArrowSwap (GArrowInversePair g (**) u) (**) u where
+  ga_swap = GArrowInversePair { forward = ga_swap , backward = ga_swap }
+-- but notice that we can't (in general) get
+-- instance GArrowDrop g => GArrowDrop (GArrowInversePair g) where ...
+
+
+
+
+--------------------------------------------------------------------------------
+-- BCPierce's symmetric lenses form a BiGArrow *with* GArrowSwap
+
+
+-- NOTE: if you uncomment, this BE SURE YOU ARE NOT USING -fcoqpass --
+-- the code below will trigger one of the not-yet-fixed bugs in the
+-- code that turns GHC CoreSyn into strongly-typed Coq expressions.
+
+{-
+data Lens x y where
+  Lens :: forall x y c1 c2 . ((x,c1)->(y,c2)) -> ((y,c2)->(x,c1)) -> Lens x y
+
+-- can we make lenses out of GArrows other than (->)?
+instance Category Lens where
+  id                          = Lens (\x -> x) (\x -> x)
+  (Lens g1 g2) . (Lens f1 f2) = Lens (\(x,(c1,c2)) -> let (y,fc) = f1 (x,c1) in  let (z,gc) = g1 (y,c2) in  (z,(fc,gc)))
+                                     (\(z,(c1,c2)) -> let (y,gc) = g2 (z,c2) in  let (x,fc) = f2 (y,c1) in  (x,(fc,gc)))
+
+instance GArrow Lens (,) () where
+  ga_first     (Lens f1 f2) = Lens (\((x1,x2),c) -> let (y,c') = f1 (x1,c) in ((y,x2),c'))
+                                   (\((x1,x2),c) -> let (y,c') = f2 (x1,c) in ((y,x2),c'))
+  ga_second    (Lens f1 f2) = Lens (\((x1,x2),c) -> let (y,c') = f1 (x2,c) in ((x1,y),c'))
+                                   (\((x1,x2),c) -> let (y,c') = f2 (x2,c) in ((x1,y),c'))
+  ga_cancell                = Lens (\(((),x),()) -> (    x ,())) 
+                                   (\(    x ,()) -> (((),x),()))
+  ga_uncancell              = Lens (\(    x ,()) -> (((),x),()))
+                                   (\(((),x),()) -> (    x ,())) 
+  ga_cancelr                = Lens (\((x,()),()) -> (    x ,())) 
+                                   (\( x    ,()) -> ((x,()),()))
+  ga_uncancelr              = Lens (\( x    ,()) -> ((x,()),()))
+                                   (\((x,()),()) -> (    x ,())) 
+  ga_assoc                  = Lens (\(((x,y),z),()) -> ((x,(y,z)),()))
+                                   (\((x,(y,z)),()) -> (((x,y),z),()))
+  ga_unassoc                = Lens (\((x,(y,z)),()) -> (((x,y),z),()))
+                                   (\(((x,y),z),()) -> ((x,(y,z)),()))
+
+instance GArrowDrop Lens (,) () where
+  ga_drop        = Lens (\(x,()) -> ((),x)) (\((),x) -> (x,()))
+instance GArrowCopy Lens (,) () where
+  ga_copy        = Lens (\(x,()) -> ((x,x),())) (\((x,_),()) -> (x,()))
+instance GArrowSwap Lens (,) () where
+  ga_swap        = Lens (\((x,y),()) -> ((y,x),())) (\((x,y),()) -> ((y,x),()))
+
+instance BiGArrow Lens (,) () where
+  biga_arr f f'  = Lens (\(x,()) -> ((f x),())) (\(x,()) -> ((f' x),()))
+  biga_inv (Lens f1 f2) = Lens f2 f1
+-}