-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathGeneric.hs
83 lines (63 loc) · 1.79 KB
/
Generic.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
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC
-fplugin BinderAnn.Generic
-fplugin-opt BinderAnn.Generic:manual
#-}
module Generic where
import Control.Monad.State
import Control.Monad.Except
import BinderAnn.Generic
----------------------------------------
-- Example 1: Arithmetic expressions
----------------------------------------
data EvalError =
DivByZero (Maybe SrcInfo)
deriving Show
type MonadEval m =
( MonadAnnotated m
, MonadError EvalError m
, MonadIO m
)
type Eval = AnnotatedT (ExceptT EvalError IO)
runEval :: Eval a -> IO (Either EvalError a)
runEval = runExceptT . evalAnnotatedT
divByZeroError :: MonadEval m => a -> m b
divByZeroError x = lookupAnn x >>= throwError . DivByZero
-- the DSL
lit :: MonadEval m => Int -> m Int
lit = return
(|+|) :: MonadEval m => Int -> Int -> m Int
(|+|) x y = lit (x + y)
(|-|) :: MonadEval m => Int -> Int -> m Int
(|-|) x y = lit (x - y)
(|*|) :: MonadEval m => Int -> Int -> m Int
(|*|) x y = lit (x * y)
(|/|) :: MonadEval m => Int -> Int -> m Int
(|/|) x y | y == 0 = divByZeroError y
| otherwise = lit (x `div` y)
-- some tests
{-# ANN test1 SrcInfo #-}
test1 :: MonadEval m => m Int
test1 = do
zero <- lit 0
one <- lit 1
false <- return False
liftIO $ print (zero, one)
one |/| zero
----------------------------------------
-- entry point
----------------------------------------
tests :: IO ()
tests = do
putStrLn "test1:"
runEval test1 >>= print