-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathVMMonad.hs
100 lines (74 loc) · 2.79 KB
/
VMMonad.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
88
89
90
91
92
93
94
95
96
97
98
99
100
module VMMonad
(VM
-- State management
,getS
,setS
-- Raise an error
,raise
-- Inject an IO operation into the VM Monad
,io2vm
-- Run a batch of VML actions
,runVM
-- Provide state transformations
,inject
-- Error handling
,handle
) where
-----------------------------------------------------------------------
-- The VM monad. Tested within the Win32 Hugs environment.
-- Author : Pablo J. Pedemonte
-- Last revision: 15-Jan-02
--
-- The Virtual Machine monad
-- Useful for several VM operations
-----------------------------------------------------------------------
import VMErr
data VM s a = VM (s -> IO (s,Either a VMErr))
unVM (VM f) = f
instance Monad (VM s) where
return a = VM $ \s -> return (s,Left a)
m >>= f = VM $ \s ->
let _f = unVM m
in do (_s,a) <- _f s
case a of
Left _a -> do { p <- unVM (f _a) _s ; return p }
Right vmErr -> return (_s,Right vmErr)
-----------------------------------------------------------------------
-- State management
-----------------------------------------------------------------------
getS :: VM s s
getS = VM $ \s -> return (s, Left s)
setS :: s -> VM s ()
setS s = VM $ \_ -> return (s, Left ())
-----------------------------------------------------------------------
-- Raise an error
-----------------------------------------------------------------------
raise :: VMErr -> VM s a
raise vmErr = VM $ \s -> return (s, Right vmErr)
-----------------------------------------------------------------------
-- Inject an IO operation into the VM Monad
-----------------------------------------------------------------------
io2vm :: IO a -> VM s a
io2vm m = VM $ \s -> do { a <- m ; return (s,Left a) }
-----------------------------------------------------------------------
-- Run a batch of VML actions
-----------------------------------------------------------------------
runVM :: VM s a -> s -> IO (s, Either a VMErr)
runVM = unVM
-----------------------------------------------------------------------
-- Inject computations based on a state type r
-- into a sequence using a state type s
-----------------------------------------------------------------------
inject :: VM r a -> (s -> r) -> (r -> s) -> (VM s a)
inject m f g = VM $ \s ->
do (r,a) <- runVM m (f s)
return (g r,a)
-----------------------------------------------------------------------
-- Exception handling
-----------------------------------------------------------------------
handle :: VM s a -> (VMErr -> VM s a) -> VM s a
handle p h = VM $
\s -> do (_s,a) <- unVM p s
case a of
Left _a -> return (_s,Left _a)
Right vmErr -> do { p <- unVM (h vmErr) _s ; return p }