2009-07-15 31 views
18

F#の値制限がどのように機能するのか分かりません。私はwikiMSDN documentationの説明を読んだ。私は理解していないことである。F#値制限エラーの理解

  1. 例えば、これは私に(this質問から撮影)値の制限のエラーを与えるなぜ、:

    let toleq (e:float<_>) a b = (abs (a - b)) < e 
    

    しかし、THSはしていません:

    これは、すべての権利を一般化され
    let toleq e (a:float<_>) b = (abs (a - b)) < e 
    
  2. ...

    let is_bigger a b = a < b 
    

    これは(これはintとして指定されている)ではない:

    let add a b = a + b 
    
  3. 暗黙のパラメータを持つ関数は、値の制限を生成する理由:

    これ:このVS

    let item_count = List.fold (fun acc _ -> 1 + acc) 0 
    

    let item_count l = List.fold (fun acc _ -> 1 + acc) 0 l 
    

    それは動作しませんどのように

)VRエラーが消えてしまいますが、その後の機能は、私はそれを使用するタイプに指定され、私はそれが一般化することにしたいコードの一部では、この機能を使用できますか?

(私は、v1.9.6.16を最新のF#を使用しています)

+0

同じトピックについての別の質問とのクロスリファレンス:http://stackoverflow.com/questions/416508/f-compiler-error-fs0030-problems-with-the-value-restriction – Benjol

答えて

16

EDIT

ベター/最近の情報はここにある:Keeping partially applied function generic

(以下オリジナル)

私は思いますここでの実用的なことは、これをあまり深く理解しようとするのではなく、むしろVRを過ぎてあなたの仕事に進むための一般的な戦略を知ることです。これはちょっとしたコップアウトの答えですが、ここではF#タイプのシステム(リリースからリリースにかけて少しずつ変わり続けています)の内部構造を理解するのに時間を費やすことは意味がありません。

私が主張する2つの主な戦略は次のとおりです。あなたは(「 - >」矢印付きタイプ)関数型と値を定義している場合、最初に、そしてeta-conversionを行うことによって、それは構文上の機能であることを確認:

// function that looks like a value, problem 
let tupleList = List.map (fun x -> x,x) 
// make it a syntactic function by adding argument to both sides 
let tupleList l = List.map (fun x -> x,x) l 

第二に、あなたはまだVRが発生した場合/問題を一般化(F#が許す限り「バックオフ」当時と)、その後、あなたが欲しいものを言って全体の型シグネチャを指定します。

// below has a problem... 
let toleq (e:float<_>) a b = (abs (a - b)) < e 
// so be fully explicit, get it working... 
let toleq<[<Measure>]'u> (e:float<'u>) (a:float<'u>) (b:float<'u>) : bool = 
    (abs (a - b)) < e 
// then can experiment with removing annotations one-by-one... 
let toleq<[<Measure>]'u> e (a:float<'u>) b = (abs (a - b)) < e 

私はそれらの2つの戦略が最善の実践的なアドバイスだと思います。それは、あなたの特定の質問に答える私の試みです。

  1. 私は分かりません。

  2. '>'は、すべての型で機能する完全な汎用関数( 'a - >' a - > bool)です。したがって、is_biggerは一般化します。一方、 '+'は、いくつかのプリミティブ型とある種の他の型で動作する「インライン」関数です。他のインライン関数内でのみ一般化することができます。そうでなければ、特定の型に固定する必要があります(またはデフォルトは 'int'になります)。 (アドホック多型の 'インライン'メソッドは、F#の数学演算子が "型クラス"の欠如を克服する方法です。)これは私が上で議論した '構文関数'の問題です。 '関数とは異なり、汎用的ではないフィールド/プロパティにコンパイルしましょう。だから、それを汎用的にしたいのであれば、それを関数にしてください。 (この規則の別の例外のためにもthis questionを参照してくださいません。)

+2

ドミトリーはこれに素晴らしい記事を書いていますもっと最近:http://blogs.msdn.com/b/mulambda/archive/2010/05/01/value-restriction-in-f.aspx – Brian

2

のF#チームの人を含む誰もが、意味のある方法でこの質問への答えを知っています。

F#型の推論システムは、コンパイラが真実を定義する意味でVB6文法とまったく同じです。

残念ですが、本当です。

+1

まあ、私はドンが答えを知っていると思います。そしてF#はまだベータ版です。ある時点で仕様を固めなければなりません。コンパイラはブラックボックスではありません。 F#コンパイラのソースは自由に利用できます。 大部分は私が同意しない限り(誰も知っていることはほとんどなく、簡潔なスペックの欠如は実際には不幸なことです)、私はあなたにdownvoteしませんでした。 – Brian

+0

すべての言語には隅々があります。 F#のほとんどは非常に安定した、非常にエレガントで実用的な言語(IMHO)です。明らかに、それはまだ進行中ですが、他のいくつかの開発言語(名前を付けずに)と比較して、F#では未来が確実に明るいです。 しかし、私はあなたにも怒鳴りませんでした。 –

+0

@Brian Donは、彼がソースにアクセスできるので、答えを知っています。 F#の型推論の "理論"はありません。 – user128807

4

副作用の存在下で多型に関するいくつかの問題に対処するために、値の制限が導入されました。 F#はOCamlからこれを継承しています。私は、すべてのMLバリエーションに値の制限があると信じています。あなたが引用したリンクの他に、あなたが読むためのfewmorelinksがあります。ハスケルは純粋なので、この制限を受けません。

あなたの質問については、質問3は本当に価値の制限に関係していると思いますが、最初の2つは価値の制限ではありません。

+0

はい。 OCamlはリラックスした値の制限を持っています.REPLではトップレベルの非一般化型変数が '' a'ではなく ''a 'として表示されます。後者は、コードが多形であり、すべての型 '' a'に対して機能することを意味します。前者は、この型でコードが単調であり、特定の型 ''a ''に対してのみ動作し、まだ決定されていないことを意味します。これは、OCamlがすべての多態性データに対して一様なデータ表現を使用するという事実によって、より簡単になります。合理化されたジェネリックスがコンパイル時に知られている正確な単形型を必要とするため、F#ではより難しくなります。 –