module Language.PureScript.Types where
import Data.Data
import Data.Generics (mkT, mkQ, everywhereBut)
import Control.Monad.Unify
import Language.PureScript.Names
newtype SkolemScope = SkolemScope { runSkolemScope :: Int } deriving (Show, Eq, Ord, Data, Typeable)
data Type
= TUnknown Unknown
| Object Type
| TypeVar String
| TypeConstructor (Qualified ProperName)
| TypeApp Type Type
| SaturatedTypeSynonym (Qualified ProperName) [Type]
| ForAll String Type (Maybe SkolemScope)
| ConstrainedType [(Qualified ProperName, Type)] Type
| Skolem Int SkolemScope
| REmpty
| RCons String Type Type deriving (Show, Eq, Data, Typeable)
tyFunction :: Type
tyFunction = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Function")
tyString :: Type
tyString = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "String")
tyNumber :: Type
tyNumber = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Number")
tyBoolean :: Type
tyBoolean = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Boolean")
tyArray :: Type
tyArray = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Array")
function :: Type -> Type -> Type
function t1 t2 = TypeApp (TypeApp tyFunction t1) t2
rowToList :: Type -> ([(String, Type)], Type)
rowToList (RCons name ty row) = let (tys, rest) = rowToList row
in ((name, ty):tys, rest)
rowToList r = ([], r)
rowFromList :: ([(String, Type)], Type) -> Type
rowFromList ([], r) = r
rowFromList ((name, t):ts, r) = RCons name t (rowFromList (ts, r))
isMonoType :: Type -> Bool
isMonoType (ForAll _ _ _) = False
isMonoType ty = True
mkForAll :: [String] -> Type -> Type
mkForAll args ty = foldl (\t arg -> ForAll arg t Nothing) ty args
unit :: Type
unit = Object REmpty
replaceTypeVars :: (Data d) => String -> Type -> d -> d
replaceTypeVars name t = everywhereBut (mkQ False isShadowed) (mkT replaceTypeVar)
where
replaceTypeVar (TypeVar v) | v == name = t
replaceTypeVar other = other
isShadowed (ForAll v _ _) | v == name = True
isShadowed _ = False