{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module FRP.Rhine.Terminal (
TerminalEventClock (..),
flowTerminal,
RunTerminalClock,
runTerminalClock,
) where
import Unsafe.Coerce (unsafeCoerce)
import Prelude hiding (putChar)
import Control.Monad.Catch (MonadMask)
import Data.Time.Clock (getCurrentTime)
import System.Terminal (Event, Interrupt, MonadInput, TerminalT, awaitEvent, runTerminalT)
import System.Terminal.Internal (Terminal)
import Control.Monad.Trans.Reader
import Control.Monad.Schedule.Class
import FRP.Rhine
data TerminalEventClock = TerminalEventClock
instance (MonadInput m, MonadIO m) => Clock m TerminalEventClock where
type Time TerminalEventClock = UTCTime
type Tag TerminalEventClock = Either Interrupt Event
initClock :: TerminalEventClock
-> RunningClockInit
m (Time TerminalEventClock) (Tag TerminalEventClock)
initClock TerminalEventClock
TerminalEventClock = do
UTCTime
initialTime <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
forall (m :: * -> *) a. Monad m => a -> m a
return
( forall (m :: * -> *) b a. Monad m => m b -> MSF m a b
constM forall a b. (a -> b) -> a -> b
$ do
Either Interrupt Event
event <- forall (m :: * -> *). MonadInput m => m (Either Interrupt Event)
awaitEvent
UTCTime
time <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
forall (m :: * -> *) a. Monad m => a -> m a
return (UTCTime
time, Either Interrupt Event
event)
, UTCTime
initialTime
)
instance GetClockProxy TerminalEventClock
instance Semigroup TerminalEventClock where
TerminalEventClock
t <> :: TerminalEventClock -> TerminalEventClock -> TerminalEventClock
<> TerminalEventClock
_ = TerminalEventClock
t
flowTerminal ::
( MonadIO m
, MonadMask m
, Terminal t
, Clock (TerminalT t m) cl
, GetClockProxy cl
, Time cl ~ Time (In cl)
, Time cl ~ Time (Out cl)
) =>
t ->
Rhine (TerminalT t m) cl () () ->
m ()
flowTerminal :: forall (m :: * -> *) t cl.
(MonadIO m, MonadMask m, Terminal t, Clock (TerminalT t m) cl,
GetClockProxy cl, Time cl ~ Time (In cl),
Time cl ~ Time (Out cl)) =>
t -> Rhine (TerminalT t m) cl () () -> m ()
flowTerminal t
term Rhine (TerminalT t m) cl () ()
clsf = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) t a.
(MonadIO m, MonadMask m, Terminal t) =>
TerminalT t m a -> t -> m a
runTerminalT t
term forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) cl.
(Monad m, Clock m cl, GetClockProxy cl, Time cl ~ Time (In cl),
Time cl ~ Time (Out cl)) =>
Rhine m cl () () -> m ()
flow Rhine (TerminalT t m) cl () ()
clsf
type RunTerminalClock m t cl = HoistClock (TerminalT t m) m cl
runTerminalClock ::
Terminal t =>
t ->
cl ->
RunTerminalClock IO t cl
runTerminalClock :: forall t cl. Terminal t => t -> cl -> RunTerminalClock IO t cl
runTerminalClock t
term cl
unhoistedClock =
HoistClock
{ monadMorphism :: forall a. TerminalT t IO a -> IO a
monadMorphism = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) t a.
(MonadIO m, MonadMask m, Terminal t) =>
TerminalT t m a -> t -> m a
runTerminalT t
term
, cl
unhoistedClock :: cl
unhoistedClock :: cl
..
}
terminalT :: ReaderT t m a -> TerminalT t m a
terminalT :: forall t (m :: * -> *) a. ReaderT t m a -> TerminalT t m a
terminalT = forall a b. a -> b
unsafeCoerce
unTerminalT :: TerminalT t m a -> ReaderT t m a
unTerminalT :: forall t (m :: * -> *) a. TerminalT t m a -> ReaderT t m a
unTerminalT = forall a b. a -> b
unsafeCoerce
instance (Monad m, MonadSchedule m) => MonadSchedule (TerminalT t m) where
schedule :: forall a.
NonEmpty (TerminalT t m a)
-> TerminalT t m (NonEmpty a, [TerminalT t m a])
schedule = forall t (m :: * -> *) a. ReaderT t m a -> TerminalT t m a
terminalT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall t (m :: * -> *) a. ReaderT t m a -> TerminalT t m a
terminalT)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
MonadSchedule m =>
NonEmpty (m a) -> m (NonEmpty a, [m a])
schedule forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall t (m :: * -> *) a. TerminalT t m a -> ReaderT t m a
unTerminalT