-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathResource.hs
70 lines (59 loc) · 2.45 KB
/
Resource.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
-- | Examples of the resource effect.
module Example.Resource where
-- base
import qualified Control.Exception as E
import Prelude hiding (print)
-- hspec
import Test.Hspec (Spec, it)
-- effet
import Control.Effect.Error
import Control.Effect.Resource
import Hspec (print, shouldPrint)
--- Example Programs -----------------------------------------------------------
-- | Type used here as virtual handle.
newtype Handle = Handle { nameOf :: String }
-- | Simple bracket with print outputs.
aBracket :: Resource m => String -> m ()
aBracket name = do
bracket
( print ("Alloc " ++ name) >> pure (Handle name) )
( \handle -> print $ "Free " ++ nameOf handle )
( \handle -> print $ "Use " ++ nameOf handle )
-- | Simple bracket with print outputs.
aBracketOnError :: Resource m => String -> m ()
aBracketOnError name = do
bracketOnError
( print ("Alloc " ++ name) >> pure (Handle name) )
( \handle -> print $ "Free " ++ nameOf handle )
( \handle -> print $ "Use " ++ nameOf handle )
-- | Bracket where the usage function throws an ArrayException.
errorBracket :: (Error String m, Resource m) => String -> m ()
errorBracket name = do
bracket
( print ("Alloc " ++ name) >> pure (Handle name) )
( \handle -> print $ "Free " ++ nameOf handle )
( \handle -> E.throw (E.UndefinedElement $ nameOf handle ) )
--- Test Cases -----------------------------------------------------------------
spec :: Spec
spec = do
it "evaluates a bracket" $
( runResourceIO -- result: (MonadBaseControl IO m, MonadIO m) => m (),
-- unified with IO ()
$ aBracket "X" ) -- effects: Resource
`shouldPrint`
"\"Alloc X\"\n\"Use X\"\n\"Free X\"\n"
it "evaluates a bracket without freeing" $
( runResourceIO -- result: (MonadBaseControl IO m, MonadIO m) => m (),
-- unified with IO ()
$ aBracketOnError "X" ) -- effects: Resource
`shouldPrint`
"\"Alloc X\"\n\"Use X\"\n"
it "evaluates a bracket with an error" $
( runResourceIO -- result: (MonadBaseControl IO m, MonadIO m) => m (Either String ()),
-- unified with IO (Either String ())
. runError -- effects: Resource
$ errorBracket "X" ) -- effects: Error String, Resource
`E.catch`
( \(_ :: E.ArrayException) -> pure (Left "Intended error") )
`shouldPrint`
"\"Alloc X\"\n\"Free X\"\n"