1 {-# OPTIONS_GHC -fno-warn-unused-do-bind -fno-warn-orphans #-}
2 {-# LANGUAGE OverloadedStrings #-}
6 -- Copyright : Tomáš Musil 2014
9 -- Maintainer : tomik.musil@gmail.com
10 -- Stability : experimental
12 -- Parser for Hindley-Milner terms and types.
19 import Data.Char (isAsciiLower, isAsciiUpper)
20 import Data.Text as T hiding (map)
21 import Data.Attoparsec.Text
22 import Control.Applicative
26 braced :: String -> String
27 braced t = "(" ++ t ++ ")"
29 instance Show Term where
31 show (Lam x (NTTerm (Lam y t))) = show (Lam (x ++ " " ++ y) t)
32 show (Lam x t) = braced $ "λ" ++ x ++ "." ++ show t
33 show (App a (NTTerm (App b c))) = show a ++ " " ++ braced ( show (App b c))
34 show (App t r) = show t ++ " " ++ show r
35 show (Let x e1 e2) = braced $ "LET " ++ x ++ " = " ++ show e1 ++ " IN " ++ show e2
37 instance Show TypedTerm where
38 show (NTTerm t) = show t
39 show (TTerm t tp) = braced $ show t ++ " :: " ++ show tp
41 instance Show Type where
42 show (Primitive t) = t
44 show (TypeFunction a b) = braced $ show a ++ " -> " ++ show b
46 instance Show TypeScheme where
47 show (TScheme t) = show t
48 show (TSForAll x t) = braced $ "∀" ++ x ++ ": " ++ show t
50 tRead :: String -> TypedTerm
51 tRead s = case parseOnly (parseTypedTerm <* endOfInput) (T.pack s) of
55 parseTerm :: Parser Term
56 parseTerm = parseLet <|>
61 parseTermNA :: Parser Term
62 parseTermNA = parseLet <|>
66 parseTypeAndTermNA :: Parser TypedTerm
67 parseTypeAndTermNA = do
71 return $! TTerm term tp
73 parseTypeAndTerm :: Parser TypedTerm
78 return $! TTerm term tp
80 parseTypedTermNA :: Parser TypedTerm
81 parseTypedTermNA = parseBraces <|>
82 parseTypeAndTermNA <|>
83 (NTTerm <$> parseTerm)
85 parseTypedTerm :: Parser TypedTerm
86 parseTypedTerm = parseBraces <|>
88 (NTTerm <$> parseTerm)
90 parseType :: Parser Type
91 parseType = parsePrimitive <|>
95 parsePrimitive :: Parser Type
97 x <- many1 $ satisfy isAsciiUpper
100 parseTypeVar :: Parser Type
102 x <- many1 $ satisfy isAsciiLower
105 parseTypeFunction :: Parser Type
106 parseTypeFunction = do
110 return $! TypeFunction a b
112 parseTypeScheme :: Parser TypeScheme
113 parseTypeScheme = parseForAll <|>
114 (TScheme <$> parseType)
116 parseForAll :: Parser TypeScheme
119 (TypeVar x) <- parseTypeVar
122 return $! TSForAll x t
124 parseBraces :: Parser TypedTerm
131 parseLet :: Parser Term
139 return $! Let x e1 e2
141 parseVar :: Parser Term
143 x <- many1 $ satisfy isAsciiLower
146 parseLambda :: Parser Term
148 char '\\' <|> char 'λ' <|> char 'L'
149 vars <- sepBy1 parseVar (char ' ')
152 let (NTTerm l) = createLambda vars t
155 parseApp :: Parser Term
157 aps <- sepBy1 parseTypedTermNA (char ' ')
158 return $! createApp aps
160 createLambda :: [Term] -> TypedTerm -> TypedTerm
161 createLambda (Var x : vs) t = NTTerm . Lam x $ createLambda vs t
162 createLambda [] t = t
163 createLambda _ _ = error "createLambda failed"
165 createApp :: [TypedTerm] -> Term
166 createApp [t,ts] = App t ts
167 createApp (t:ts:tss) = createApp (NTTerm (App t ts) : tss)
168 createApp [] = error "empty createApp"
172 -- TODO prop> t == tRead (show (t :: Term))