こんにちは、Haskell で C ライクな静的型付け言語のインタープリターを書いています。コードの実行前に型チェックを実行したいのですが、いくつか問題があります。まず、以下に私の抽象構文からの型定義をいくつか示します。
newtype Ident = Ident String deriving (Eq,Ord,Show)
data Exp = {-- some other value constructors --} | EFuncWithParams Ident [Exp]
data Type = TInt | TDouble | {-- some other value constructors --} | TFunction [Exp]
type TCM a = ErrorT String (Reader Env) a
TCM は、エラーを報告し、環境を渡すためのものです。
typeof (EVar v) = do
env <- ask
case M.lookup v env of
Nothing -> throwError $ "undefined variable" ++ v ++ "\n"
Just t - > return t
今、式のタイプをチェックしたいので、チェックを実行する次の関数があります:
typeof Exp :: Exp -> TCM Type
1 つを除くすべてのケースに対して定義されます。
typeof (EFuncWithParams f l)
私はここで立ち往生しています。私がすべきだと思うのは、f の型をチェックすることです (つまり、最初にそれが本当に関数かどうかをチェックするということです)。f の定義に記録されている引数の型が、実際に渡される引数の型と一致するかどうかを確認します。残念ながら、私は Haskell の初心者であり、正しい方法で表現する方法がわかりません。どんな提案でも大歓迎です:)
編集: わかりました、以前ここに書いたことには暗示されていないかもしれませんが、EFuncWithParams Ident [Exp] は実際には関数呼び出しであり (はい、多少誤解を招くことはわかっています)、 f(2 + 3, a, b[0]) であり、これが TFunction [Exp] を使用した理由です。関数の宣言と定義はステートメントであり、次のように定義されます。
data Function_def =
Func Type_specifier Declarator Compound_stm
deriving (Eq,Ord,Show)
ここで、宣言子は次のとおりです。
data Declarator = FuncDec Ident Parameter_declarations
パラメータ宣言は Type_specifiers と Idents のリストです
私がすべきだと思うのは、宣言を確認しながら関数型をマップに保存し、ここでフェッチすることです。私も持っていることを意味します:
typeof_stm :: Stm -> TCM Type -- Function_def is a statement
問題は、型チェック ステートメント用の別の関数があり、ある関数 (typeof_stm など) で使用されるマップが別の関数 (typeof など) に自動的に渡されるかどうか疑問です。これが起こる方法はないと思いますが、間違っているかもしれません。