2017-05-24 5 views
2

シグネチャで多形参照定数を定数にする方法はありますか?シグネチャ内のSML多型参照

このコードはコンパイルが、私は必要なものではありません。

signature NAME = sig 
    type 'a name 
    val empty : 'a name 
end 

structure Name :> NAME = struct 
    datatype 'a name = Nil | Val of 'a 
    val empty = Nil 
end 

は、必要な参照を追加:

signature NAME = sig 
    type 'a name 
    val empty : 'a name ref 
end 

structure Name :> NAME = struct 
    datatype 'a name = Nil | Val of 'a 
    val empty = ref Nil 
end 

は、次のエラーを生成します:

error: Structure does not match signature. 
    Signature: val empty: 'a name ref 
    Structure: val empty: 'a name ref 
    Reason: Can't match 'a to 'a (Type variable is free in surrounding scope) 
Found near struct datatype 'a name = Nil | Val of 'a val empty = ref Nil end 

答えて

2

これはしていません実際には署名と関係があります。あなたは(トップレベルで)書いた場合は、問題の同じ種類を取得したい:

val emptyListRef = ref nil 
val emptyIntList = (! emptyListRef) : int list 
val emptyStringList = (! emptyListRef) : string list 

問題がemptyListRef —またはあなたのケースでempty —が多型ではないということです。 (あなたのコンパイラはempty'a name refを入力していると主張、しかし何それ本当に手段はemptyフォーム?? name refのいくつかの種類を持っているということです、そして、それはまだ??がどうなるかを考え出していません。)

この制限が作ります

あなたが int Nameを保持し、私としてそれからの読み取りに emptyを設定
val() = empty := Val 3 
val Val (x : string) = !empty 

:あなたはempty多型だった場合、その後、あなたはのようなものを書くことができるだろうと考える意味それはstring Nameを持っていた。あなたがそれをしないと信じるようにコンパイラに説得する方法はありません。

右辺がコンストラクタの組み合わせ(ref!)と定数とfnの式のようないくつかの単純な形式のうちの1つを取る場合、値バインディングは多態性しか許されません。安全であることが知られている(上記の不正行為を可能にすることができない点で)。このルールはvalue restrictionと呼ばれます。あなたはGoogleより多くの情報を得ることができます。

+0

ありがとうございます!私は 'datatype'がname = Nil | 'val h = ref:val = h:= Val 5'のValはエラーを生成しませんが、これは次のようになります: 'datatype 'a name = Nil | val of 'val h = ref Nil; val _ = h:= Val 5'(セミコロンに気付く) – zlotnleo

+1

@zlotnleo:ようこそ!なぜセミコロンが違いを生むのか - 標準ML *の定義は、コンパイラが 'empty = ref Nil'のような非一般化可能なバインディングの宣言をどのように扱うべきかは実際には言いません。あなたのコンパイラは、バインディングの種類を「ハング」して、空の型を推論できるように、より多くの情報を得るのを待っているようです。セミコロン(最上位の宣言を終了する)に達すると、コンパイラは明らかにそれを断念します(エラーを返すか、デフォルトまたはダミーの型を割り当てるなど)。 – ruakh