-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEmbed.hs
87 lines (76 loc) · 2.97 KB
/
Embed.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
-- | Examples of the embed effect.
module Example.Embed where
-- base
import Control.Monad (guard)
import Data.Maybe (listToMaybe, maybeToList)
import Prelude hiding (print)
-- hspec
import Test.Hspec (Spec, it, shouldBe)
-- effet
import Control.Effect.Embed
import Control.Effect.Reader
import Hspec (print, shouldPrint)
--- Example Programs -----------------------------------------------------------
-- | Find shared numbers of two reader-based lists using the list monad.
intersect :: (Reader' "xs" [Int] m, Reader' "ys" [Int] m, Embed [] m) => m Int
intersect = do
xs <- ask' @"xs"
ys <- ask' @"ys"
embed $ do
x <- xs
y <- ys
guard $ x == y
pure x
-- | Divide two numbers using the maybe monad.
divide :: Embed Maybe m => Maybe Int -> Maybe Int -> m Int
divide mx my = embed $ do
x <- mx
y <- my
guard $ y /= 0
pure $ x `div` y
-- | Performs multiple divisions.
divisions :: Embed [] m => Maybe Int -> m Int
divisions divisor = do
a <- runEmbed maybeToList $ divide (Just 3) (Just 1)
b <- runEmbed maybeToList $ divide (Just 2) divisor
c <- runEmbed maybeToList $ divide (Just 5) divisor
d <- runEmbed maybeToList $ divide (Just 9) (Just 4)
embed [a,b,c,d]
-- | Uses embed instead of liftIO to print texts with prefix and suffix (reader).
simulateLiftIO :: (Embed IO m, Reader String m) => String -> m ()
simulateLiftIO prefix = do
suffix <- ask
embed $ do
print $ prefix ++ "Hello" ++ suffix
print $ prefix ++ "World" ++ suffix
--- Test Cases -----------------------------------------------------------------
spec :: Spec
spec = do
it "evaluates intersect with []" $
( runReader' @"ys" [2,3,4] -- effects: Embed [], result: [Int]
. runReader' @"xs" [1,2,3] -- effects: Reader' "ys" [Int], Embed []
$ intersect ) -- effects: Reader' "xs" [Int], Reader' "ys" [Int], Embed []
`shouldBe` [2,3]
it "evaluates intersect with Maybe" $
( runEmbed listToMaybe -- effects: Embed Maybe, result: Maybe Int
. runReader' @"ys" [2,3,4] -- effects: Embed []
. runReader' @"xs" [1,2,3] -- effects: Reader' "ys" [Int], Embed []
$ intersect ) -- effects: Reader' "xs" [Int], Reader' "ys" [Int], Embed []
`shouldBe` Just 2
it "evaluates division" $
( divide (Just 10) (Just 3) ) -- effects: Embed Maybe, result: Maybe Int
`shouldBe` Just 3
it "evaluates division by zero" $
( divide (Just 2) (Just 0) ) -- effects: Embed Maybe, result: Maybe Int
`shouldBe` Nothing
it "evaluates divisions" $
( divisions (Just 2) ) -- effects: Embed [], result: [Int]
`shouldBe` [3,1,2,2]
it "evaluates divisions by zero" $
( divisions Nothing ) -- effects: Embed Maybe, result: Maybe [Int]
`shouldBe` []
it "evaluates simulateLiftIO" $
( runReader " [S]" -- effects: Embed IO, result: IO ()
$ simulateLiftIO "[P] " ) -- effects: Embed IO, Reader String
`shouldPrint`
"\"[P] Hello [S]\"\n\"[P] World [S]\"\n"