proton-0.0.1: src/Proton/Loop.hs
{-# LANGUAGE InstanceSigs #-}
module Proton.Loop where
import Data.Profunctor
import Data.Profunctor.Traversing
import Proton.Types
import Data.Profunctor.Choice
-- Cochoice represents iteration/looping
type Loop s t a b = forall p. Cochoice p => p a b -> p s t
type Loop' s a = Loop s s a a
data CoPrism a b s t = CoPrism (s -> a) (b -> Either a t)
instance Profunctor (CoPrism a b) where
dimap f g (CoPrism project match) = CoPrism (project . f) (fmap g . match)
instance Cochoice (CoPrism a b) where
unright :: forall d a' b'. CoPrism a b (Either d a') (Either d b') -> CoPrism a b a' b'
unright (CoPrism project match) = CoPrism (project . Right) (go . match)
where
go :: Either a (Either d b') -> Either a b'
go (Left a) = Left a
go (Right (Right b)) = Right b
go (Right (Left d)) = Left (project $ Left d)
loop :: forall p s t a b. Cochoice p
=> (s -> a) -> (b -> Either a t) -> Optic p s t a b
loop inject step = unright . dimap (either id inject) step
-- loop' :: forall p s t a b. (Cochoice p, Traversing p)
-- => (s -> a) -> (b -> Either a t) -> Optic p s t a b
-- loop' inject step = unright . dimap (either id inject) step
-- iterM :: forall s t a b . Optic (Star ((,) [a])) s t a b -> (a -> Either a b) -> s -> ([a], t)
-- iterM o f s = g s
-- where
-- Star (g :: s -> ([a], t)) = (o . unright . lmap (either id id)) $ Star (wrapper . f)
-- wrapper :: Either a b -> ([a], Either a b)
-- wrapper (Left a) = ([a], Left a)
-- wrapper (Right b) = ([], Right b)
iterM :: forall s t a . Optic (Star ((,) [a])) s t a a -> (a -> Either a a) -> s -> ([a], t)
iterM o f s = g s
where
Star (g :: s -> ([a], t)) = o . unright . lmap (either id id) $ Star (wrapper . f)
wrapper :: Either a a -> ([a], Either a a)
wrapper (Left a) = ([a], Left a)
wrapper (Right b) = ([b], Right b)
tester :: Int -> Either Int Int
tester a
| a < 10 = Left (succ a)
| otherwise = Right (succ a)
-- iter :: forall f p s t a b. (Alternative f, Cochoice p)
-- => Optic p s t a b
-- iter = _