-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathException.purs
108 lines (90 loc) · 2.8 KB
/
Exception.purs
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
-- | This module defines an effect, actions and handlers for working
-- | with JavaScript exceptions.
module Control.Monad.Eff.Exception
( EXCEPTION
, Error
, error
, message
, name
, stack
, throwException
, catchException
, throw
, try
) where
import Prelude
import Control.Monad.Eff (Eff, kind Effect)
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
-- | This effect is used to annotate code which possibly throws exceptions
foreign import data EXCEPTION :: Effect
-- | The type of JavaScript errors
foreign import data Error :: Type
instance showError :: Show Error where
show = showErrorImpl
foreign import showErrorImpl :: Error -> String
-- | Create a JavaScript error, specifying a message
foreign import error :: String -> Error
-- | Get the error message from a JavaScript error
foreign import message :: Error -> String
-- | Get the error name when defined, or fallback to 'Error'
foreign import name :: Error -> String
-- | Get the stack trace from a JavaScript error
stack :: Error -> Maybe String
stack = stackImpl Just Nothing
foreign import stackImpl
:: (forall a. a -> Maybe a)
-> (forall a. Maybe a)
-> Error
-> Maybe String
-- | Throw an exception
-- |
-- | For example:
-- |
-- | ```purescript
-- | main = do
-- | x <- readNumber
-- | when (x < 0) $ throwException $
-- | error "Expected a non-negative number"
-- | ```
foreign import throwException
:: forall a eff
. Error
-> Eff (exception :: EXCEPTION | eff) a
-- | Catch an exception by providing an exception handler.
-- |
-- | This handler removes the `EXCEPTION` effect.
-- |
-- | For example:
-- |
-- | ```purescript
-- | main = catchException print do
-- | Console.log "Exceptions thrown in this block will be logged to the console"
-- | ```
foreign import catchException
:: forall a eff
. (Error -> Eff eff a)
-> Eff (exception :: EXCEPTION | eff) a
-> Eff eff a
-- | A shortcut allowing you to throw an error in one step. Defined as
-- | `throwException <<< error`.
throw :: forall eff a. String -> Eff (exception :: EXCEPTION | eff) a
throw = throwException <<< error
-- | Runs an Eff and returns eventual Exceptions as a `Left` value. If the
-- | computation succeeds the result gets wrapped in a `Right`.
-- |
-- | For example:
-- |
-- | ```purescript
-- | -- Notice that there is no EXCEPTION effect
-- | main :: forall eff. Eff (console :: CONSOLE, fs :: FS | eff) Unit
-- | main = do
-- | result <- try (readTextFile UTF8 "README.md")
-- | case result of
-- | Right lines ->
-- | Console.log ("README: \n" <> lines )
-- | Left error ->
-- | Console.error ("Couldn't open README.md. Error was: " <> show error)
-- | ```
try :: forall eff a. Eff (exception :: EXCEPTION | eff) a -> Eff eff (Either Error a)
try action = catchException (pure <<< Left) (Right <$> action)