Skip to content

Commit 1a83f65

Browse files
committed
HandleReader example
1 parent 1a1c65e commit 1a83f65

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

bluefin-examples/bluefin-examples.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ library
7474
import: warnings
7575
exposed-modules:
7676
Bluefin.Examples.DB,
77+
Bluefin.Examples.HandleReader,
7778
Bluefin.Examples.Random,
7879
Bluefin.Examples.Stream.InsideAndOut,
7980
Bluefin.Examples.Stream.Many,
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
module Bluefin.Examples.HandleReader where
2+
3+
import Bluefin.Compound (Handle (mapHandle), useImpl)
4+
import Bluefin.Eff (Eff, runEff, (:&), (:>))
5+
import Bluefin.HandleReader
6+
( HandleReader,
7+
askHandle,
8+
localHandle,
9+
runHandleReader,
10+
)
11+
import Bluefin.IO (effIO)
12+
import Bluefin.State (State, evalState, get, modify)
13+
import Bluefin.Stream (Stream, forEach, yield)
14+
15+
-- | @SummableStream@ is a @Stream@ that can be locally overridden
16+
newtype SummableStream e = MkSummableStream (HandleReader (Stream Int) e)
17+
18+
-- | Run the @SummableStream@ in a @Stream@
19+
runSummableStream ::
20+
(e1 :> es) =>
21+
Stream Int e1 ->
22+
(forall e. SummableStream e -> Eff (e :& es) r) ->
23+
Eff es r
24+
runSummableStream y k =
25+
runHandleReader y $ \hr -> do
26+
k (MkSummableStream hr)
27+
28+
-- | Yield to the @SummableStream@
29+
yieldSummable ::
30+
(e1 :> es) =>
31+
SummableStream e1 ->
32+
Int ->
33+
Eff es ()
34+
yieldSummable (MkSummableStream hr) n = onHandle hr (\y -> yield y n)
35+
36+
onHandle ::
37+
(Handle h, e1 :> es) =>
38+
HandleReader h e1 ->
39+
(forall e. h e -> Eff e r) ->
40+
Eff es r
41+
onHandle hr k = do
42+
h <- askHandle hr
43+
k h
44+
45+
-- | Locally override the @SummableStream@ so that @yieldSummable@, as
46+
-- well as yielding to the @Stream@ as normal, also accumulates into
47+
-- the @State@.
48+
sumYields ::
49+
(e1 :> es, e2 :> es) =>
50+
SummableStream e1 ->
51+
State Int e2 ->
52+
Eff es r ->
53+
Eff es r
54+
sumYields (MkSummableStream hr) st body = do
55+
yorig <- askHandle hr
56+
-- In the body, hr is modified so that it both modifies the State
57+
-- and yields to the original Stream
58+
forEach
59+
( \ynested -> do
60+
localHandle
61+
hr
62+
( \_ -> mapHandle ynested
63+
)
64+
(useImpl body)
65+
)
66+
( \i -> do
67+
-- yield to the original Stream
68+
yield yorig i
69+
-- modify the State
70+
modify st (+ i)
71+
)
72+
73+
-- ghci> exampleHandleReader
74+
-- 1
75+
-- 2
76+
-- 3
77+
-- 4
78+
-- Total from summed block was 7
79+
exampleHandleReader :: IO ()
80+
exampleHandleReader = runEff $ \io -> do
81+
evalState 0 $ \st -> do
82+
forEach
83+
( \y -> runSummableStream y $ \sb -> do
84+
yieldSummable sb 1
85+
yieldSummable sb 2
86+
sumYields sb st $ do
87+
-- The yields in this body will be accumulated into st
88+
yieldSummable sb 3
89+
yieldSummable sb 4
90+
)
91+
(effIO io . print @Int)
92+
93+
total <- get st
94+
let msg = "Total from summed block was " <> show total
95+
effIO io (putStrLn msg)

0 commit comments

Comments
 (0)