Skip to content

Commit

Permalink
add Accum and dynamic dispatch Output
Browse files Browse the repository at this point in the history
  • Loading branch information
janmasrovira committed Feb 8, 2024
1 parent 22cfd9c commit 6910c03
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 18 deletions.
24 changes: 24 additions & 0 deletions src/Juvix/Prelude/Effects/Accum.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Juvix.Prelude.Effects.Accum where

import Data.Kind qualified as GHC
import Juvix.Prelude.Base hiding (Effect, Output, output, runOutputList)
import Juvix.Prelude.Effects.Base

data Accum (o :: GHC.Type) :: Effect

type instance DispatchOf (Accum _) = 'Static 'NoSideEffects

newtype instance StaticRep (Accum o) = Accum
{ _unAccum :: [o]
}

runAccumList :: Eff (Accum o ': r) a -> Eff r ([o], a)
runAccumList m = do
(a, Accum s) <- runStaticRep (Accum mempty) m
return (reverse s, a)

ignoreAccum :: Eff (Accum o ': r) a -> Eff r a
ignoreAccum m = snd <$> runAccumList m

accum :: (Accum o :> r) => o -> Eff r ()
accum o = overStaticRep (\(Accum l) -> Accum (o : l))
47 changes: 29 additions & 18 deletions src/Juvix/Prelude/Effects/Output.hs
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
module Juvix.Prelude.Effects.Output where

import Data.Kind qualified as GHC
import Juvix.Prelude.Base (fst, mapM_, return, reverse, (<$>))
import Effectful.Dispatch.Dynamic
import Juvix.Prelude.Base hiding (Effect, Output, interpret, output, reinterpret, runOutputList)
import Juvix.Prelude.Effects.Accum
import Juvix.Prelude.Effects.Base
import System.Time.Extra

data Output (o :: GHC.Type) :: Effect
data Output (o :: GHC.Type) :: Effect where
Output :: o -> Output o m ()

type instance DispatchOf (Output _) = 'Static 'NoSideEffects

newtype instance StaticRep (Output o) = Output [o]
makeEffect ''Output

runOutputEff :: (o -> Eff r ()) -> Eff (Output o ': r) a -> Eff r a
runOutputEff handle m = do
(ls, a) <- runOutputList m
mapM_ handle ls
return a
runOutputEff handle =
interpret $ \_ -> \case
Output x -> handle x

runOutputList :: Eff (Output o ': r) a -> Eff r ([o], a)
runOutputList m = do
(a, Output s) <- runStaticRep (Output []) m
return (reverse s, a)

ignoreOutput :: Eff (Output o ': r) a -> Eff r (a)
ignoreOutput m = fst <$> runStaticRep (Output []) m

output :: (Output o :> r) => o -> Eff r ()
output o = overStaticRep (\(Output l) -> Output (o : l))
runOutputList = reinterpret runAccumList $ \_ -> \case
Output x -> accum x

ignoreOutput :: Eff (Output o ': r) a -> Eff r a
ignoreOutput = interpret $ \_ -> \case
Output {} -> return ()

example1 :: IO ()
example1 =
runEff $
runOutputEff (\n -> putStrLn ("hey " <> show @Natural n)) (go 3)

go :: (Output Natural :> r, IOE :> r) => Natural -> Eff r ()
go = \case
0 -> return ()
n -> do
output n
liftIO (sleep 1)
go (pred n)

0 comments on commit 6910c03

Please sign in to comment.