module Types.Types where
import Data.Char (isDigit)
import Data.List (intercalate,isPrefixOf)
import qualified Data.Set as Set
type X = Int
data Type = LambdaT Type Type
| VarT X
| ADT String [Type]
| Super (Set.Set Type)
deriving (Eq, Ord)
data Scheme = Forall [X] [Context String Constraint] Type deriving (Eq, Ord)
data Constraint = Type :=: Type
| Type :<: Type
| X :<<: Scheme
deriving (Eq, Ord, Show)
data Context c v = Context c v deriving (Eq, Show)
ctx c = Context ("`" ++ show c ++ "'")
extendCtx ctx2 (Context ctx1 c) = Context (ctx1 ++ " in " ++ ctx2) c
instance (Ord a, Eq c) => Ord (Context c a) where
compare (Context _ x) (Context _ y) = compare x y
tipe t = ADT t []
int = tipe "Int"
float = tipe "Float"
number = Super (Set.fromList [ int, float ])
char = tipe "Char"
bool = tipe "Bool"
string = listOf char
text = tipe "Text"
time = float
date = tipe "Date"
month = tipe "Month"
day = tipe "Day"
element = tipe "Element"
direction = tipe "Direction"
form = tipe "Form"
line = tipe "Line"
shape = tipe "Shape"
color = tipe "Color"
position = tipe "Position"
location = tipe "Location"
listOf t = ADT "List" [t]
signalOf t = ADT "Signal" [t]
tupleOf ts = ADT ("Tuple" ++ show (length ts)) ts
maybeOf t = ADT "Maybe" [t]
pairOf t = tupleOf [t,t]
point = pairOf int
appendable t = Super (Set.fromList [ string, text, listOf t ])
comparable = Super (Set.fromList [ int, float, char, string, time, date ])
jsBool = tipe "JSBool"
jsNumber = tipe "JSNumber"
jsString = tipe "JSString"
jsElement = tipe "JSElement"
jsArray t = ADT "JSArray" [t]
jsTuple ts = ADT ("JSTuple" ++ show (length ts)) ts
jsonValue = tipe "JsonValue"
jsonObject = tipe "JsonObject"
infixr ==>
t1 ==> t2 = LambdaT t1 t2
infix 8 -:
name -: tipe = (,) name $ Forall [] [] tipe
hasType t = map (-: t)
parens = ("("++) . (++")")
instance Show Type where
show t =
case t of
{ LambdaT t1@(LambdaT _ _) t2 -> parens (show t1) ++ " -> " ++ show t2
; LambdaT t1 t2 -> show t1 ++ " -> " ++ show t2
; VarT x -> 't' : show x
; ADT "List" [ADT "Char" []] -> "String"
; ADT "List" [tipe] -> "[" ++ show tipe ++ "]"
; ADT name cs ->
if isTupleString name
then parens . intercalate "," $ map show cs
else case cs of [] -> name
_ -> parens $ name ++ " " ++ unwords (map show cs)
; Super ts -> "{" ++ (intercalate "," . map show $ Set.toList ts) ++ "}"
}
instance Show Scheme where
show (Forall xs cs t) = "Forall " ++ show xs ++ cs' ++ "\n " ++ show t
where cs' = concatMap (concatMap ("\n "++) . lines . show) cs
isTupleString str = "Tuple" `isPrefixOf` str && all isDigit (drop 5 str)