-- |
--- Module : Lambda.Type
+-- Module : HM
-- Copyright : Tomáš Musil 2014
-- License : BSD-3
--
-- Maintainer : tomik.musil@gmail.com
-- Stability : experimental
--
--- Data types for Hindley-Milner types.
+-- This is a toy implementation of λ-calculus with Hindley-Milner type system.
-
-module Lambda.Type
+module HM
( -- * Types
Type(..)
+ , Term
-- * Type inference
, algW
) where
-import Lambda.Term
-
-type TypeVarName = String
-type TypeName = String
-
-data Type = Primitive TypeName | TypeVar TypeVarName | TypeFunction Type Type deriving (Show)
-data TypeScheme = TScheme Type | TSForAll TypeVarName TypeScheme deriving (Show)
-
-data HMTerm = HMTerm Term TypeScheme | HMLet VarName HMTerm HMTerm TypeScheme
+import HM.Term
+import HM.Parser
type Substitution = TypeScheme -> TypeScheme
unify :: TypeScheme -> TypeScheme -> Either String Substitution
unify (TScheme (Primitive a)) (TScheme (Primitive b)) | a == b = Right id
unify (TScheme (TypeVar a)) (TScheme (TypeVar b)) | a == b = Right id
-unify a b = Left "cannot unify " ++ show a ++ " with " ++ show b
+unify a b = Left $ "cannot unify " ++ show a ++ " with " ++ show b
algW :: HMTerm -> Either String TypeScheme
algW (HMTerm (Var _) t) = Right t
algW (HMTerm (Lambda x t) (TScheme p)) = do
let v = TScheme (TypeVar fresh)
- np <- substitute v x t
+ np = substitute v x t
unify p np
algW (HMTerm (App u v) t) = do
tu <- algW u
--- /dev/null
+{-# OPTIONS_GHC -fno-warn-unused-do-bind -fno-warn-orphans #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- |
+-- Module : HM.Parser
+-- Copyright : Tomáš Musil 2014
+-- License : BSD-3
+--
+-- Maintainer : tomik.musil@gmail.com
+-- Stability : experimental
+--
+-- Parser for Hindley-Milner terms and types.
+
+module HM.Parser
+ ( tRead
+ , parseTerm
+ ) where
+
+import Data.Text as T hiding (map)
+import Data.Attoparsec.Text
+import Control.Applicative
+
+import HM.Term
+import qualified Lambda.Parser.Fancy as Lambda
+import qualified Lambda.Term as Lambda
+
+braced :: String -> String
+braced t = "(" ++ t ++ ")"
+
+instance Show Term where
+ show (Var x) = x
+ show (Lam x (NTTerm (Lam y t))) = show (Lam (x ++ " " ++ y) t)
+ show (Lam x t) = braced $ "λ" ++ x ++ "." ++ show t
+ show (App a (NTTerm (App b c))) = show a ++ " " ++ (braced $ show (App b c))
+ show (App t r) = show t ++ " " ++ show r
+ show (Let x e1 e2) = braced $ "let " ++ x ++ " = " ++ show e1 ++ " in " ++ show e2
+
+instance Show TypedTerm where
+ show (NTTerm t) = show t
+ show (TTerm t tp) = braced $ show t ++ " :: " ++ show tp
+
+instance Show Type where
+ show (Primitive t) = t
+ show (TypeVar t) = t
+ show (TypeFunction a b) = braced $ show a ++ " -> " ++ show b
+
+instance Show TypeScheme where
+ show (TScheme t) = show t
+ show (TSForAll x t) = braced $ "∀" ++ x ++ ": " ++ show t
+
+tRead :: String -> Term
+tRead = undefined
+
+parseTerm :: Parser TypedTerm
+parseTerm = parseLet <|>
+ (lambdaToHM <$> Lambda.parseTerm)
+
+parseLet :: Parser TypedTerm
+parseLet = do
+ char '('
+ string "let "
+ (Lambda.Var x) <- Lambda.parseVar
+ string " = "
+ e1 <- lambdaToHM <$> Lambda.parseTerm
+ string " in "
+ e2 <- lambdaToHM <$> Lambda.parseTerm
+ char ')'
+ return . NTTerm $ Let x e1 e2
+
+lambdaToHM :: Lambda.Term -> TypedTerm
+lambdaToHM (Lambda.Var x) = NTTerm $ Var x
+lambdaToHM (Lambda.App t u) = NTTerm $ App (lambdaToHM t) (lambdaToHM u)
+lambdaToHM (Lambda.Lambda x t) = NTTerm $ Lam x (lambdaToHM t)
+
+-- |
+-- TODO prop> t == tRead (show (t :: Term))
+
+{-
+tRead :: String -> Term
+tRead s = case parseOnly (parseTerm <* endOfInput) (T.pack s) of
+ (Right t) -> t
+ (Left e) -> error e
+-}
--- /dev/null
+-- |
+-- Module : HM.Term
+-- Copyright : Tomáš Musil 2014
+-- License : BSD-3
+--
+-- Maintainer : tomik.musil@gmail.com
+-- Stability : experimental
+--
+-- Data types for Hindley-Milner terms.
+
+module HM.Term
+ ( -- * Types
+ VarName
+ , TypeVarName
+ , TypeName
+ , Term(..)
+ , TypedTerm(..)
+ , Type(..)
+ , TypeScheme(..)
+ ) where
+
+type VarName = String
+type TypeVarName = String
+type TypeName = String
+
+data Type = Primitive TypeName | TypeVar TypeVarName | TypeFunction Type Type
+data TypeScheme = TScheme Type | TSForAll TypeVarName TypeScheme
+
+data Term = Var VarName | Lam VarName TypedTerm | App TypedTerm TypedTerm | Let VarName TypedTerm TypedTerm
+data TypedTerm = NTTerm Term | TTerm Term TypeScheme