effet-0.3.0.2: examples/Example/Embed.hs
-- | 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"