-
Notifications
You must be signed in to change notification settings - Fork 28
/
2014-02-25-dtypes-2.hs
101 lines (79 loc) · 2.63 KB
/
2014-02-25-dtypes-2.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
101
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Singletons
import Data.Singletons.TH
import Data.Typeable
import Language.Haskell.Interpreter
-- Only used for demonstration purposes
import Data.Dynamic
import Data.Maybe
$(singletons [d|
data PgType = PgInt | PgString
data PgFunction = PgReturn PgType | PgArrow PgType PgFunction
|])
-- These are exactly as before
type family InterpretType (t :: PgType) :: *
type instance InterpretType 'PgInt = Int
type instance InterpretType 'PgString = String
type family InterpretFunction (t :: PgFunction) :: *
type instance InterpretFunction ('PgReturn t) = InterpretType t
type instance InterpretFunction ('PgArrow t ts) = InterpretType t -> InterpretFunction ts
funType :: SPgFunction t -> InterpretFunction t
funType (SPgReturn _) = undefined
funType (SPgArrow _ ts) = \_ -> funType ts
{-
-- This doesn't type check:
firstAttempt :: String -> PgFunction -> IO ()
firstAttempt code sig = withSomeSing sig $ \s -> do
runInterpreter $ do
setImports [("Prelude")]
interpret code (funType s)
putStrLn "It didn't crash!"
-}
data Dict a where
Dict :: a => Dict a
pgTypeTypeable :: SPgType t -> Dict (Typeable (InterpretType t))
pgTypeTypeable SPgInt = Dict
pgTypeTypeable SPgString = Dict
pgFunTypeTypeable :: SPgFunction t -> Dict (Typeable (InterpretFunction t))
pgFunTypeTypeable (SPgReturn t) = pgTypeTypeable t
pgFunTypeTypeable (SPgArrow t ts) =
case pgTypeTypeable t of
Dict ->
case pgFunTypeTypeable ts of
Dict ->
Dict
goal :: String -> PgFunction -> IO ()
goal code signature = withSomeSing signature $ \s ->
case pgFunTypeTypeable s of
Dict -> do
f <- runInterpreter $ do
setImports [("Prelude")]
interpret code (funType s)
case f of
Left error ->
print error
Right f' ->
-- Apply arguments to f'
putStrLn "Everything type checked!"
final :: String -> PgFunction -> [Dynamic] -> IO ()
final code signature args = withSomeSing signature $ \s ->
case pgFunTypeTypeable s of
Dict -> do
f <- runInterpreter $ do
setImports [("Prelude")]
interpret code (funType s)
case f of
Left error ->
print error
Right f' ->
apply s args f'
where
apply :: SPgFunction t -> [Dynamic] -> InterpretFunction t -> IO ()
apply (SPgReturn SPgInt) _ i = print i
apply (SPgReturn SPgString) _ i = print i
apply (SPgArrow t ts) (x : xs) f = case pgTypeTypeable t of
Dict -> apply ts xs (f (fromJust $ fromDynamic x))