{-# LANGUAGE GADTs, -- match on Refl for type equality
ExistentialQuantification -- forall b ans. Yield ...
#-}
module Control.Ev.Ctl(
Marker
, markerEq
, Ctl(Pure)
, runCtl
, prompt
, yield
, unsafeIO
, unsafePromptIORef
) where
import Prelude hiding (read,flip)
import Control.Monad( ap, liftM )
import Data.Type.Equality( (:~:)( Refl ) )
import Control.Monad.Primitive
import Unsafe.Coerce ( unsafeCoerce )
import System.IO.Unsafe ( unsafePerformIO )
import Data.IORef
data Marker a = Marker !Integer
instance Show (Marker a) where
show :: Marker a -> String
show (Marker Integer
i) = Integer -> String
forall a. Show a => a -> String
show Integer
i
instance Eq (Marker a) where
Marker a
m1 == :: Marker a -> Marker a -> Bool
== Marker a
m2 = Marker a -> Marker a -> Bool
forall a b. Marker a -> Marker b -> Bool
markerEq Marker a
m1 Marker a
m2
markerEq :: Marker a -> Marker b -> Bool
markerEq :: Marker a -> Marker b -> Bool
markerEq (Marker Integer
i) (Marker Integer
j) = (Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
j)
mmatch :: Marker a -> Marker b -> Maybe ((:~:) a b)
mmatch :: Marker a -> Marker b -> Maybe (a :~: b)
mmatch (Marker Integer
i) (Marker Integer
j) | Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
j = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just ((Any :~: Any) -> a :~: b
forall a b. a -> b
unsafeCoerce Any :~: Any
forall k (a :: k). a :~: a
Refl)
mmatch Marker a
_ Marker b
_ = Maybe (a :~: b)
forall a. Maybe a
Nothing
{-# NOINLINE unique #-}
unique :: IORef Integer
unique :: IORef Integer
unique = IO (IORef Integer) -> IORef Integer
forall a. IO a -> a
unsafePerformIO (Integer -> IO (IORef Integer)
forall a. a -> IO (IORef a)
newIORef Integer
0)
{-# NOINLINE freshMarker #-}
freshMarker :: (Marker a -> Ctl a) -> Ctl a
freshMarker :: (Marker a -> Ctl a) -> Ctl a
freshMarker Marker a -> Ctl a
f
= let m :: Integer
m = IO Integer -> Integer
forall a. IO a -> a
unsafePerformIO (IO Integer -> Integer) -> IO Integer -> Integer
forall a b. (a -> b) -> a -> b
$
do Integer
i <- IORef Integer -> IO Integer
forall a. IORef a -> IO a
readIORef IORef Integer
unique;
IORef Integer -> Integer -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Integer
unique (Integer
iInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1);
Integer -> IO Integer
forall (m :: * -> *) a. Monad m => a -> m a
return Integer
i
in Integer -> Ctl a -> Ctl a
seq Integer
m (Marker a -> Ctl a
f (Integer -> Marker a
forall a. Integer -> Marker a
Marker Integer
m))
data Ctl a = Pure { Ctl a -> a
result :: !a }
| forall ans b.
Yield{ ()
marker :: !(Marker ans),
()
op :: !((b -> Ctl ans) -> Ctl ans),
()
cont :: !(b -> Ctl a)
}
{-# INLINE yield #-}
yield :: Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> Ctl b
yield :: Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> Ctl b
yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op = Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl b) -> Ctl b
forall a ans b.
Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl a) -> Ctl a
Yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op b -> Ctl b
forall a. a -> Ctl a
Pure
{-# INLINE kcompose #-}
kcompose :: (b -> Ctl c) -> (a -> Ctl b) -> a -> Ctl c
kcompose :: (b -> Ctl c) -> (a -> Ctl b) -> a -> Ctl c
kcompose b -> Ctl c
g a -> Ctl b
f a
x = case (a -> Ctl b
f a
x) of
Pure b
x -> b -> Ctl c
g b
x
Yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op b -> Ctl b
cont -> Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl c) -> Ctl c
forall a ans b.
Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl a) -> Ctl a
Yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op (b -> Ctl c
g (b -> Ctl c) -> (b -> Ctl b) -> b -> Ctl c
forall b c a. (b -> Ctl c) -> (a -> Ctl b) -> a -> Ctl c
`kcompose` b -> Ctl b
cont)
{-# INLINE bind #-}
bind :: Ctl a -> (a -> Ctl b) -> Ctl b
bind :: Ctl a -> (a -> Ctl b) -> Ctl b
bind (Pure a
x) a -> Ctl b
f = a -> Ctl b
f a
x
bind (Yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op b -> Ctl a
cont) a -> Ctl b
f = Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl b) -> Ctl b
forall a ans b.
Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl a) -> Ctl a
Yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op (a -> Ctl b
f (a -> Ctl b) -> (b -> Ctl a) -> b -> Ctl b
forall b c a. (b -> Ctl c) -> (a -> Ctl b) -> a -> Ctl c
`kcompose` b -> Ctl a
cont)
instance Functor Ctl where
fmap :: (a -> b) -> Ctl a -> Ctl b
fmap = (a -> b) -> Ctl a -> Ctl b
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM
instance Applicative Ctl where
pure :: a -> Ctl a
pure = a -> Ctl a
forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: Ctl (a -> b) -> Ctl a -> Ctl b
(<*>) = Ctl (a -> b) -> Ctl a -> Ctl b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad Ctl where
return :: a -> Ctl a
return a
x = a -> Ctl a
forall a. a -> Ctl a
Pure a
x
Ctl a
e >>= :: Ctl a -> (a -> Ctl b) -> Ctl b
>>= a -> Ctl b
f = Ctl a -> (a -> Ctl b) -> Ctl b
forall a b. Ctl a -> (a -> Ctl b) -> Ctl b
bind Ctl a
e a -> Ctl b
f
{-# INLINE mprompt #-}
mprompt :: Marker a -> Ctl a -> Ctl a
mprompt :: Marker a -> Ctl a -> Ctl a
mprompt Marker a
m p :: Ctl a
p@(Pure a
_) = Ctl a
p
mprompt Marker a
m (Yield Marker ans
n (b -> Ctl ans) -> Ctl ans
op b -> Ctl a
cont)
= let cont' :: b -> Ctl a
cont' b
x = Marker a -> Ctl a -> Ctl a
forall a. Marker a -> Ctl a -> Ctl a
mprompt Marker a
m (b -> Ctl a
cont b
x) in
case Marker a -> Marker ans -> Maybe (a :~: ans)
forall a b. Marker a -> Marker b -> Maybe (a :~: b)
mmatch Marker a
m Marker ans
n of
Maybe (a :~: ans)
Nothing -> Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl a) -> Ctl a
forall a ans b.
Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl a) -> Ctl a
Yield Marker ans
n (b -> Ctl ans) -> Ctl ans
op b -> Ctl a
cont'
Just a :~: ans
Refl -> (b -> Ctl ans) -> Ctl ans
op b -> Ctl a
b -> Ctl ans
cont'
{-# INLINE prompt #-}
prompt :: (Marker a -> Ctl a) -> Ctl a
prompt :: (Marker a -> Ctl a) -> Ctl a
prompt Marker a -> Ctl a
action
= (Marker a -> Ctl a) -> Ctl a
forall a. (Marker a -> Ctl a) -> Ctl a
freshMarker ((Marker a -> Ctl a) -> Ctl a) -> (Marker a -> Ctl a) -> Ctl a
forall a b. (a -> b) -> a -> b
$ \Marker a
m ->
Marker a -> Ctl a -> Ctl a
forall a. Marker a -> Ctl a -> Ctl a
mprompt Marker a
m (Marker a -> Ctl a
action Marker a
m)
runCtl :: Ctl a -> a
runCtl :: Ctl a -> a
runCtl (Pure a
x) = a
x
runCtl (Yield Marker ans
_ (b -> Ctl ans) -> Ctl ans
_ b -> Ctl a
_) = String -> a
forall a. HasCallStack => String -> a
error String
"Unhandled operation"
{-# INLINE unsafeIO #-}
unsafeIO :: IO a -> Ctl a
unsafeIO :: IO a -> Ctl a
unsafeIO IO a
io = let x :: a
x = IO a -> a
forall (m :: * -> *) a. PrimBase m => m a -> a
unsafeInlinePrim IO a
io in a -> Ctl a -> Ctl a
seq a
x (a -> Ctl a
forall a. a -> Ctl a
Pure a
x)
mpromptIORef :: IORef a -> Ctl b -> Ctl b
mpromptIORef :: IORef a -> Ctl b -> Ctl b
mpromptIORef IORef a
r Ctl b
action
= case Ctl b
action of
p :: Ctl b
p@(Pure b
_) -> Ctl b
p
Yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op b -> Ctl b
cont
-> do a
val <- IO a -> Ctl a
forall a. IO a -> Ctl a
unsafeIO (IORef a -> IO a
forall a. IORef a -> IO a
readIORef IORef a
r)
let cont' :: b -> Ctl b
cont' b
x = do IO () -> Ctl ()
forall a. IO a -> Ctl a
unsafeIO (IORef a -> a -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef a
r a
val)
IORef a -> Ctl b -> Ctl b
forall a b. IORef a -> Ctl b -> Ctl b
mpromptIORef IORef a
r (b -> Ctl b
cont b
x)
Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl b) -> Ctl b
forall a ans b.
Marker ans -> ((b -> Ctl ans) -> Ctl ans) -> (b -> Ctl a) -> Ctl a
Yield Marker ans
m (b -> Ctl ans) -> Ctl ans
op b -> Ctl b
cont'
unsafePromptIORef :: a -> (Marker b -> IORef a -> Ctl b) -> Ctl b
unsafePromptIORef :: a -> (Marker b -> IORef a -> Ctl b) -> Ctl b
unsafePromptIORef a
init Marker b -> IORef a -> Ctl b
action
= (Marker b -> Ctl b) -> Ctl b
forall a. (Marker a -> Ctl a) -> Ctl a
freshMarker ((Marker b -> Ctl b) -> Ctl b) -> (Marker b -> Ctl b) -> Ctl b
forall a b. (a -> b) -> a -> b
$ \Marker b
m ->
do IORef a
r <- IO (IORef a) -> Ctl (IORef a)
forall a. IO a -> Ctl a
unsafeIO (a -> IO (IORef a)
forall a. a -> IO (IORef a)
newIORef a
init)
IORef a -> Ctl b -> Ctl b
forall a b. IORef a -> Ctl b -> Ctl b
mpromptIORef IORef a
r (Marker b -> IORef a -> Ctl b
action Marker b
m IORef a
r)