module Effectful.Zoo.Console.Static
  ( Console,
    runConsole,
    runConsoleTextToHandle,
    runConsoleTextToStdout,
    runConsoleTextToStderr,
    withConsole,
    print,
    local,
  ) where

import Data.Text.IO qualified as T
import Data.Kind
import Effectful
import Effectful.Zoo.Console.Data.Writer
import Effectful.Zoo.Core
import Effectful.Dispatch.Static
import HaskellWorks.Prelude
import System.IO qualified as IO

data Console (i :: Type) :: Effect

type instance DispatchOf (Console i) = Static NoSideEffects

newtype instance StaticRep (Console i) = Console (Writer i)

runConsole :: ()
  => r <: IOE
  => HasCallStack
  => UnliftStrategy
  -> (HasCallStack => i -> Eff r ())
  -> Eff (Console i : r) a
  -> Eff r a
runConsole :: forall (r :: [Effect]) i a.
(r <: IOE, HasCallStack) =>
UnliftStrategy
-> (HasCallStack => i -> Eff r ())
-> Eff (Console i : r) a
-> Eff r a
runConsole UnliftStrategy
strategy HasCallStack => i -> Eff r ()
run Eff (Console i : r) a
f = do
  Writer i
s <- UnliftStrategy -> (i -> Eff r ()) -> Eff r (Writer i)
forall (r :: [Effect]) i.
(r <: IOE) =>
UnliftStrategy -> (i -> Eff r ()) -> Eff r (Writer i)
mkWriter UnliftStrategy
strategy i -> Eff r ()
HasCallStack => i -> Eff r ()
run
  StaticRep (Console i) -> Eff (Console i : r) a -> Eff r a
forall (e :: Effect) (sideEffects :: SideEffects) (es :: [Effect])
       a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects,
 MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es a
evalStaticRep (Writer i -> StaticRep (Console i)
forall i. Writer i -> StaticRep (Console i)
Console Writer i
s) Eff (Console i : r) a
f

runConsoleTextToHandle :: ()
  => HasCallStack
  => Handle
  -> Eff (Console Text : r) a
  -> Eff r a
runConsoleTextToHandle :: forall (r :: [Effect]) a.
HasCallStack =>
Handle -> Eff (Console Text : r) a -> Eff r a
runConsoleTextToHandle Handle
h =
  StaticRep (Console Text) -> Eff (Console Text : r) a -> Eff r a
forall (e :: Effect) (sideEffects :: SideEffects) (es :: [Effect])
       a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects,
 MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es a
evalStaticRep (StaticRep (Console Text) -> Eff (Console Text : r) a -> Eff r a)
-> StaticRep (Console Text) -> Eff (Console Text : r) a -> Eff r a
forall a b. (a -> b) -> a -> b
$ Writer Text -> StaticRep (Console Text)
forall i. Writer i -> StaticRep (Console i)
Console (Writer Text -> StaticRep (Console Text))
-> Writer Text -> StaticRep (Console Text)
forall a b. (a -> b) -> a -> b
$ (Text -> IO ()) -> Writer Text
forall i. (i -> IO ()) -> Writer i
Writer ((Text -> IO ()) -> Writer Text) -> (Text -> IO ()) -> Writer Text
forall a b. (a -> b) -> a -> b
$ Handle -> Text -> IO ()
T.hPutStrLn Handle
h

runConsoleTextToStdout :: ()
  => HasCallStack
  => Eff (Console Text : r) a
  -> Eff r a
runConsoleTextToStdout :: forall (r :: [Effect]) a.
HasCallStack =>
Eff (Console Text : r) a -> Eff r a
runConsoleTextToStdout =
  Handle -> Eff (Console Text : r) a -> Eff r a
forall (r :: [Effect]) a.
HasCallStack =>
Handle -> Eff (Console Text : r) a -> Eff r a
runConsoleTextToHandle Handle
IO.stdout

runConsoleTextToStderr :: ()
  => HasCallStack
  => Eff (Console Text : r) a
  -> Eff r a
runConsoleTextToStderr :: forall (r :: [Effect]) a.
HasCallStack =>
Eff (Console Text : r) a -> Eff r a
runConsoleTextToStderr =
  Handle -> Eff (Console Text : r) a -> Eff r a
forall (r :: [Effect]) a.
HasCallStack =>
Handle -> Eff (Console Text : r) a -> Eff r a
runConsoleTextToHandle Handle
IO.stderr

withConsoleSerialiser :: ()
  => HasCallStack
  => (Writer i -> Writer o)
  -> Eff (Console o : r) a
  -> Eff (Console i : r) a
withConsoleSerialiser :: forall i o (r :: [Effect]) a.
HasCallStack =>
(Writer i -> Writer o)
-> Eff (Console o : r) a -> Eff (Console i : r) a
withConsoleSerialiser Writer i -> Writer o
f Eff (Console o : r) a
m = do
  Writer i
writer <- Eff (Console i : r) (Writer i)
forall (r :: [Effect]) i.
(HasCallStack, r <: Console i) =>
Eff r (Writer i)
getWriter
  let Writer i
_ = Writer i
writer
  Eff r a -> Eff (Console i : r) a
forall (es :: [Effect]) a (e :: Effect). Eff es a -> Eff (e : es) a
raise (Eff r a -> Eff (Console i : r) a)
-> Eff r a -> Eff (Console i : r) a
forall a b. (a -> b) -> a -> b
$ StaticRep (Console o) -> Eff (Console o : r) a -> Eff r a
forall (e :: Effect) (sideEffects :: SideEffects) (es :: [Effect])
       a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects,
 MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es a
evalStaticRep (Writer o -> StaticRep (Console o)
forall i. Writer i -> StaticRep (Console i)
Console (Writer i -> Writer o
f Writer i
writer)) Eff (Console o : r) a
m

withConsole :: ()
  => HasCallStack
  => (o -> i)
  -> Eff (Console o : r) a
  -> Eff (Console i : r) a
withConsole :: forall o i (r :: [Effect]) a.
HasCallStack =>
(o -> i) -> Eff (Console o : r) a -> Eff (Console i : r) a
withConsole =
  (Writer i -> Writer o)
-> Eff (Console o : r) a -> Eff (Console i : r) a
forall i o (r :: [Effect]) a.
HasCallStack =>
(Writer i -> Writer o)
-> Eff (Console o : r) a -> Eff (Console i : r) a
withConsoleSerialiser ((Writer i -> Writer o)
 -> Eff (Console o : r) a -> Eff (Console i : r) a)
-> ((o -> i) -> Writer i -> Writer o)
-> (o -> i)
-> Eff (Console o : r) a
-> Eff (Console i : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (o -> i) -> Writer i -> Writer o
forall a' a. (a' -> a) -> Writer a -> Writer a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap

getWriter :: ()
  => HasCallStack
  => r <: Console i
  => Eff r (Writer i)
getWriter :: forall (r :: [Effect]) i.
(HasCallStack, r <: Console i) =>
Eff r (Writer i)
getWriter = do
  Console Writer i
i <- Eff r (StaticRep (Console i))
forall (e :: Effect) (sideEffects :: SideEffects) (es :: [Effect]).
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
Eff es (StaticRep e)
getStaticRep
  Writer i -> Eff r (Writer i)
forall a. a -> Eff r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Writer i
i

print :: ()
  => HasCallStack
  => r <: Console i
  => r <: IOE
  => i
  -> Eff r ()
print :: forall (r :: [Effect]) i.
(HasCallStack, r <: Console i, r <: IOE) =>
i -> Eff r ()
print i
i = do
  Writer i
writer <- Eff r (Writer i)
forall (r :: [Effect]) i.
(HasCallStack, r <: Console i) =>
Eff r (Writer i)
getWriter
  IO () -> Eff r ()
forall a. IO a -> Eff r a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Eff r ()) -> IO () -> Eff r ()
forall a b. (a -> b) -> a -> b
$ Writer i
writer.run i
i

local :: ()
  => HasCallStack
  => r <: Console i
  => (i -> i)
  -> Eff r a
  -> Eff r a
local :: forall (r :: [Effect]) i a.
(HasCallStack, r <: Console i) =>
(i -> i) -> Eff r a -> Eff r a
local i -> i
f =
  (StaticRep (Console i) -> StaticRep (Console i))
-> Eff r a -> Eff r a
forall (e :: Effect) (sideEffects :: SideEffects) (es :: [Effect])
       a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects, e :> es) =>
(StaticRep e -> StaticRep e) -> Eff es a -> Eff es a
localStaticRep ((StaticRep (Console i) -> StaticRep (Console i))
 -> Eff r a -> Eff r a)
-> (StaticRep (Console i) -> StaticRep (Console i))
-> Eff r a
-> Eff r a
forall a b. (a -> b) -> a -> b
$ \(Console Writer i
s) -> Writer i -> StaticRep (Console i)
forall i. Writer i -> StaticRep (Console i)
Console ((i -> i) -> Writer i -> Writer i
forall a' a. (a' -> a) -> Writer a -> Writer a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap i -> i
f Writer i
s)