@@ -13,8 +13,6 @@ The most interesting property of that class is that it can be
1313instantiated by both covariant (like Parser) and contravariant (like Printer)
1414functors. Therefore it can be used as a common interface to unify
1515parsing and pretty printing.
16−
17−Operator names are up to bikeshedding :)
1816-}
1917module Data.SemiIsoFunctor where
2018
@@ -25,6 +23,8 @@ import Control.Lens.SemiIso
2523infixl 3 /|/
2624infixl 4 /$/
2725infixl 5 /*/, /*, */
26+infixl 1 //=
27+infixr 1 =//
2828
2929-- | A functor from the category of semi-isomorphisms to Hask.
3030--
@@ -63,7 +63,15 @@ class SemiIsoFunctor f where
6363--
6464-- > TODO (they should be fine)
6565class SemiIsoFunctor f => SemiIsoApply f where
66+ siunit :: f ()
67+ siunit = sipure id
68+
6669 sipure :: ASemiIso' a () -> f a
70+ sipure ai = ai /$/ siunit
71+
72+ sipureCo :: ASemiIso' () a -> f a
73+ sipureCo ai = ai `simapCo` siunit
74+
6775 (/*/) :: f a -> f b -> f (a, b)
6876
6977 (/*) :: f a -> f () -> f a
@@ -72,7 +80,7 @@ class SemiIsoFunctor f => SemiIsoApply f where
7280 (*/) :: f () -> f b -> f b
7381 f */ g = unit . swapped /$/ f /*/ g
7482
75− {-# MINIMAL sipure, (/*/) #-}
83+ {-# MINIMAL (siunit | sipure), (/*/) #-}
7684
7785-- | Equivalent of 'Alternative' for 'SemiIsoFunctor'.
7886--
@@ -90,6 +98,21 @@ class SemiIsoApply f => SemiIsoAlternative f where
9098
9199 {-# MINIMAL siempty, (/|/) #-}
92100
101+class SemiIsoApply m => SemiIsoMonad m where
102+ (//=) :: m a -> (a -> m b) -> m (a, b)
103+ m //= f = swapped /$/ (f =// m)
104+
105+ (=//) :: (b -> m a) -> m b -> m (a, b)
106+ f =// m = swapped /$/ (m //= f)
107+
108+class SemiIsoMonad m => SemiIsoFix m where
109+ sifix :: (a -> m a) -> m a
110+ sifix f = dup /$/ (f =//= f)
111+ where dup = semiIso (\a -> Right (a, a)) (Right . fst)
112+
113+ (=//=) :: (a -> m b) -> (b -> m a) -> m (a, b)
114+ f =//= g = sifix (\(a, b) -> g b /*/ f a)
115+
93116-- | Equivalent of 'sequence'.
94117--
95118-- Note that it is not possible to write sequence_, because