2015-10-02 3 views
7

私は小さな言語のためにF#でDSLを実装しようとしています。残念なことにコンパイラは、(ファントム型を介して)追加の型情報を保持するようにノードを制約しようとすると、自分のトラックで私を死に至らせてしまいます。コードのこのコンストラクトは、コードの汎用性が低くなります...ファントムタイプに適用すると

次の行は、問題を示しています

type Expr<'a> = 
| Int of int 
| Eq of Expr<int> * Expr<int> 
| Not of Expr<bool> 

let rec to_string (expr: Expr<'a>) = 
    match expr with 
    | Int(n) -> string n 
    | Eq(x, y) -> sprintf "%s == %s" (to_string x) (to_string y) 
    | Not(b) -> sprintf "!%s" (to_string b) 

コンパイラによる構造to_string x次の警告を発行:次の行、構造上、ということに続き

construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type 'int'.

to_string bこのエラーを発行します:

Type mismatch. Expecting a Expr<int> but given a Expr<bool> The type int does not match the type bool

私はこの振る舞いを回避する方法を見つけることができないと思うし、実際に私はこのコードが私が予想していたより一般的でない原因を見つけることができません。可能であれば、私はファントムタイプを完全に放棄しないソリューションを好むだろう。

私は基本的に何か間違っていますか?これはコンパイラのバグでしょうか?

答えて

9

あなたはto_string機能ジェネリックにする必要があります。

let rec to_string<'a> (expr:Expr<'a>) : string = 
    match expr with 
    | Int(n) -> string n 
    | Eq(x, y) -> sprintf "%s == %s" (to_string x) (to_string y) 
    | Not(b) -> sprintf "!%s" (to_string b) 

あなたは

Not (Eq (Int 1, Int 2)) 
|> to_string 
関数を呼び出すときの型パラメータを推測されます
関連する問題