proton-0.0.1: src/Proton/Coalgebraic.hs
{-# LANGUAGE InstanceSigs #-}
module Proton.Coalgebraic where
import Proton.Types
import Data.Profunctor
import Proton.Prisms
import Proton.Review
type Coalgebraic s t a b = forall p. MChoice p => Optic p s t a b
type Coalgebraic' s a = Coalgebraic s s a a
swapEither :: Either a b -> Either b a
swapEither (Left a) = Right a
swapEither (Right a) = Left a
class Profunctor p => MChoice p where
mleft' :: p a b -> p (Either a m) (Either b m)
mleft' = dimap swapEither swapEither . mright'
mright' :: p a b -> p (Either m a) (Either m b)
mright' = dimap swapEither swapEither . mleft'
instance MChoice (->) where
mright' = right'
instance Applicative f => MChoice (Star f) where
mright' = right'
instance (Monoid r) => MChoice (Forget r) where
mright' = right'
instance Traversable f => MChoice (Costar f) where
mright' :: forall a b m. Costar f a b -> Costar f (Either m a) (Either m b)
mright' (Costar f) = (Costar (fmap f . sequenceA))
coprism :: (b -> t) -> (s -> Either t a) -> Coalgebraic s t a b
coprism rev split = dimap split (either id rev) . mright'
coalgPrism :: Prism s t a b -> Coalgebraic s t a b
coalgPrism pr = coprism (review pr) (matching pr)
_Just' :: Coalgebraic (Maybe a) (Maybe b) a b
_Just' = coalgPrism _Just
_Right' :: Coalgebraic (Either e a) (Either e b) a b
_Right' = coalgPrism _Right