packages feed

proton-0.0.4: src/Data/Profunctor/Cont.hs

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE BlockArguments #-}
module Data.Profunctor.Cont where

-- Profunctor experiments on continuations

import Data.Profunctor
import Data.Profunctor.Arrow
import Data.Function
import qualified Control.Category as C
import Control.Category ((>>>))
import Data.Void

data ContP r a b =
    ContP {runContP :: a -> ((b -> r) -> r) }
    deriving Functor

instance C.Category (ContP r) where
 id = ContP (&)
 ContP bCrR . ContP aBrR = ContP $ \a cr ->
     aBrR a $ \b -> bCrR b cr

instance Profunctor (ContP r) where
  dimap l r (ContP f) = fmap r $ ContP (\a cr -> f (l a) cr)

instance ProfunctorApply (ContP r) where
  app = ContP \(ContP aBrR, a) br -> aBrR a br

class Profunctor p => ProfunctorCont p where
  -- callCC :: (p a b -> p x a) -> p x a
  -- callCC :: (p a x -> p a (Either x b)) -> p a b
  -- callCC :: (p (Either a a) x -> p a x) -> p a a
  -- callCC :: (p (Either b x) x -> p a b) -> p a b
  -- callCC :: (p b x -> p a b) -> p a b
  -- callCC :: p ((a -> p q b) -> p q a, q) a
  callCC :: (p a b -> p x a) -> p x a

instance Choice (ContP r) where
  right' (ContP f) = ContP $ \eCA eCBR ->
      case eCA of
          Left c -> eCBR (Left c)
          Right a -> f a (eCBR . Right)

instance Strong (ContP r) where
  first' (ContP aBrR) = ContP \(a, c) bcr -> aBrR a (bcr . (,c))

instance ProfunctorCont (ContP r) where
  callCC f = ContP \q ar ->
    let ContP x = f $ ContP \a _ -> ar a
     in x q ar

evalContP :: ContP r a r -> a -> r
evalContP (ContP f) a = f a id

reset :: ContP r a r -> ContP r' a r
reset  = arr . evalContP

shift :: ContP r (ContP r (a -> r) r) a
shift = ContP (evalContP)

neutralize :: ContP r r x
neutralize = ContP (\r _ -> r)

testP :: ContP String Int Int -- ContP String Int Int
testP = catcher >>> arr succ >>>  arr succ >>> arr succ
  where
    catcher :: ContP String Int Int
    catcher = dimap (\n -> if even n then Right n else Left n) (either absurd id) (lmap show neutralize +++ C.id)

testP'' :: ContP String Int Int
testP'' = callCC \cc ->
    catcher cc >>> arr succ >>> arr succ >>> arr succ
  where
    catcher :: ContP String Int Int -> ContP String Int Int
    catcher p = dimap (splitPred even) unify (p +++ C.id)

splitPred :: (a -> Bool) -> a -> Either a a
splitPred predicate a = (if predicate a then Right a else Left a)

unify :: Either a a -> a
unify = either id id


-- helper :: (a -> Bool) -> [a] -> ContT r f (Maybe a)
-- helper predicate xs = do
--     callCC $ \cc -> do
--         case find predicate xs of
--           Just i -> cc (Just i)
--           Nothing -> pure Nothing

-- helper' :: (Monad m, Monoid r) => (a -> Bool) -> [a] -> ContT r m a
-- helper' predicate xs = do
--     shiftT $ \cc -> do
--         getAp $ flip foldMap xs $ \x ->
--                     Ap $ if predicate x
--                             then lift (cc x)
--                             else pure mempty

-- helper'' :: (Monad m, Monoid r) => (r -> Bool) -> [r] -> ContT r m r
-- helper'' predicate xs = do
--     callCC $ \outer -> do
--         shiftT $ \inner -> do
--             foldl' (go inner outer) (pure mempty) xs
--             -- getAp $ flip foldMap xs $ \x ->
--             --             Ap $ if predicate x
--             --                     then outer _
--             --                     else lift $ inner x
--   where
--     go inner outer mr a
--       | predicate a = mr >>= outer
--       | otherwise = liftA2 (<>) mr (lift $ inner a)

-- stopWhen :: (Representable p, Rep p ~ f) => p (Maybe Int) r -> p [Int] r
-- stopWhen = withCapture (helper even)

-- stopWhen' :: (Monoid r, Monad m, Representable p, Rep p ~ m) => p Int r -> p [Int] r
-- stopWhen' = withCapture (helper' even)

-- stopWhen'' :: (Monad m, Representable p, Rep p ~ m) => p [a] [a] -> p [[a]] [a]
-- stopWhen'' = withCapture (helper'' ((>3) . length))


-- -- Optic s r a r =
-- withCapture :: (Representable p, Rep p ~ f) => (s -> ContT r f a) -> p a r -> p s r
-- withCapture f p =
--     tabulate $ \b ->
--         let ContT g = (f b)
--             handler = sieve p
--          in g handler


-- tester :: [[ Int ]] -> IO [Int]
-- tester = runStar $ stopWhen'' (Star go')
--   where
--     go' i = print i >> pure i
--     go (Just i) = print i >> pure [i]
--     go Nothing = pure []

-- -- class Profunctor p => Capture p where