Skip to content

Commit a9807e2

Browse files
committed
Add Effectful.Input.Const, Effectful.Output.Array and Effectful.Coroutine
1 parent 2d54743 commit a9807e2

File tree

5 files changed

+119
-2
lines changed

5 files changed

+119
-2
lines changed

effectful-core/effectful-core.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ library
8282
c-sources: cbits/utils.c
8383

8484
exposed-modules: Effectful
85+
Effectful.Coroutine
8586
Effectful.Dispatch.Dynamic
8687
Effectful.Dispatch.Static
8788
Effectful.Dispatch.Static.Primitive
@@ -90,6 +91,7 @@ library
9091
Effectful.Error.Static
9192
Effectful.Exception
9293
Effectful.Fail
94+
Effectful.Input.Const
9395
Effectful.Internal.Effect
9496
Effectful.Internal.Env
9597
Effectful.Internal.Monad
@@ -101,6 +103,7 @@ library
101103
Effectful.Labeled.State
102104
Effectful.Labeled.Writer
103105
Effectful.NonDet
106+
Effectful.Output.Array
104107
Effectful.Prim
105108
Effectful.Provider
106109
Effectful.Provider.List
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module Effectful.Input.Const
2+
( -- * Effect
3+
Input
4+
5+
-- ** Handlers
6+
, runInput
7+
8+
-- ** Operations
9+
, input
10+
) where
11+
12+
import Data.Kind
13+
14+
import Effectful
15+
import Effectful.Dispatch.Static
16+
17+
data Input (i :: Type) :: Effect
18+
19+
type instance DispatchOf (Input i) = Static NoSideEffects
20+
newtype instance StaticRep (Input i) = Input i
21+
22+
runInput
23+
:: HasCallStack
24+
=> i
25+
-- ^ The input.
26+
-> Eff (Input i : es) a
27+
-> Eff es a
28+
runInput = evalStaticRep . Input
29+
30+
input :: (HasCallStack, Input i :> es) => Eff es i
31+
input = do
32+
Input i <- getStaticRep
33+
pure i
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
module Effectful.Output.Array
2+
( -- * Effect
3+
Output
4+
5+
-- ** Handlers
6+
, runOutput
7+
8+
-- ** Operations
9+
, output
10+
11+
-- * Re-exports
12+
, Array
13+
) where
14+
15+
import Control.Monad.Primitive
16+
import Data.Kind
17+
import Data.Primitive.Array
18+
19+
import Effectful
20+
import Effectful.Dispatch.Static
21+
import Effectful.Internal.Utils
22+
import Effectful.Internal.Env
23+
24+
data Output (o :: Type) :: Effect
25+
26+
type instance DispatchOf (Output o) = Static NoSideEffects
27+
data instance StaticRep (Output o) = Output !Int !(MutableArray RealWorld o)
28+
29+
runOutput :: HasCallStack => Eff (Output o : es) a -> Eff es (a, Array o)
30+
runOutput action = unsafeEff $ \es0 -> do
31+
arr <- newArray 0 undefinedValue
32+
inlineBracket
33+
(consEnv (Output 0 arr) relinkOutput es0)
34+
unconsEnv
35+
(\es -> (,) <$> unEff action es <*> (getArray =<< getEnv es))
36+
where
37+
getArray (Output size arr) = freezeArray arr 0 size
38+
39+
output :: (HasCallStack, Output o :> es) => o -> Eff es ()
40+
output o = unsafeEff $ \es -> do
41+
Output size arr0 <- getEnv es
42+
let len0 = sizeofMutableArray arr0
43+
arr <- case size `compare` len0 of
44+
GT -> error $ "size (" ++ show size ++ ") > len0 (" ++ show len0 ++ ")"
45+
LT -> pure arr0
46+
EQ -> do
47+
let len = growCapacity len0
48+
arr <- newArray len undefinedValue
49+
copyMutableArray arr 0 arr0 0 size
50+
pure arr
51+
writeArray arr size $! o
52+
putEnv es $ Output (size + 1) arr
53+
54+
----------------------------------------
55+
56+
relinkOutput :: Relinker StaticRep (Output o)
57+
relinkOutput = Relinker $ \_ (Output size arr0) -> do
58+
arr <- cloneMutableArray arr0 0 (sizeofMutableArray arr0)
59+
pure $ Output size arr
60+
61+
undefinedValue :: HasCallStack => a
62+
undefinedValue = error "Undefined value"

effectful/bench/Main.hs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,25 @@ import Countdown
1515
import FileSizes
1616
import Unlift
1717

18+
----------------------------------------
19+
20+
import Control.Monad
21+
import Effectful
22+
import Effectful.Coroutine
23+
24+
benchOutput
25+
:: (forall r es. Eff (Output Int : es) r -> Eff es (r, x))
26+
-> Int
27+
-> IO x
28+
benchOutput run n = fmap snd . runEff . run $ forM_ [1..n] output
29+
1830
main :: IO ()
1931
main = defaultMain
20-
[ concurrencyBenchmark
32+
[ bgroup "output"
33+
[ bench "array" $ nfAppIO (benchOutput runOutputArray) 1000
34+
, bench "list" $ nfAppIO (benchOutput runOutputList) 1000
35+
]
36+
, concurrencyBenchmark
2137
, unliftBenchmark
2238
, bgroup "countdown" $ map countdown [1000, 2000, 3000]
2339
, bgroup "countdown (extra)" $ map countdownExtra [1000, 2000, 3000]

effectful/effectful.cabal

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,21 @@ library
113113
Effectful.FileSystem.Effect
114114

115115
reexported-modules: Effectful
116+
, Effectful.Coroutine
116117
, Effectful.Dispatch.Dynamic
117118
, Effectful.Dispatch.Static
118-
, Effectful.Error.Static
119119
, Effectful.Error.Dynamic
120+
, Effectful.Error.Static
120121
, Effectful.Exception
121122
, Effectful.Fail
123+
, Effectful.Input.Const
122124
, Effectful.Labeled
123125
, Effectful.Labeled.Error
124126
, Effectful.Labeled.Reader
125127
, Effectful.Labeled.State
126128
, Effectful.Labeled.Writer
127129
, Effectful.NonDet
130+
, Effectful.Output.Array
128131
, Effectful.Prim
129132
, Effectful.Provider
130133
, Effectful.Provider.List

0 commit comments

Comments
 (0)