2013-08-23 11 views
6

は、以下のナンセンスラムダを考えてみましょう:F#のパターンマッチング風変わり

function 
| [] -> "Empty list" 
| hd::tl -> "Not so empty list" 

これが正常に動作します。

function 
| [] -> "Empty list" 
| hd::tl & l -> "Not so empty list" 

を再びナンセンスな理由のために、(と私はas代わりの&を使用して同じ効果を得ることができることを知っているが、これはすべてのコード・ゴルフ問題に関係しています。今、次のように私はそれを書き換えますこの質問には関係しません)。今度はF#コンパイラが私に教えてくれます:

警告FS0025:不完全なパターンがこの式にマッチします。 の例の場合、値 '[]'は、 パターンでカバーされていないケースを示している可能性があります。

これは意味をなさない - 私は最初のルールで[]のケースを明示的に処理しています。私は[]に関して最初の機能から2番目の機能に変わったものは見ません。いずれの関数の第2の規則もそれに適合していないが、第2の関数だけが警告を与える。私がしたのは、何でもと一致するパターンを追加しただけです。

もちろん、空のリストで2番目の関数を呼び出すことは成功します。

この警告が発生した正当な理由はありますか、F#パターンの検証にはいくつかの単純な違いがありますか?より高度なパターンを採用すると、このようなケースがいくつか見受けられますが、これはかなり基本的なもののようです。問題が一般的には解決できない場合でも、この種のケースはコンパイラで特別な処理を行うのに十分なほど一般的なようです。

+1

このように '&'が使われたことはありません。あなたはそれが何をしているかに関するいくつかの文書にリンクすることができますか? – JaredPar

+3

@JaredPar - ここでANDパターンを参照してください。http://msdn.microsoft.com/en-us/library/dd547125.aspx基本的には頭、尾、リスト全体を一つにまとめることができることを意味します。 –

答えて

6

この場合はF#コンパイラが実用的だと思います。

最後に、二番目のルールは、入力リストxs上の制約として表現することができる。

xs = hd :: tl && xs = l 

F#コンパイラは&&制約を探求していないようです。制約は任意に複雑であり、&の使用は非常にまれであるため、これは妥当です。

は、我々は partial active patternsと同様の問題を持っている:

let (|Empty|_|) = function 
    | [] -> Some() 
    | _ -> None 

let (|NonEmpty|_|) = function 
    | _ :: _ -> Some() 
    | _ -> None 

// warning FS0025 
let f = function 
    | Empty -> "Empty list" 
    | NonEmpty -> "Not so empty list" 

は、この問題を解決するには、次のことができます。

  • lは単なる結合であるため、より適切である利用as代わりの&、。
  • ワイルドカードパターンを最後に追加すると、警告が表示されなくなります。私は通常nowarn "25"を使用して警告を抑制します

    let f = 
        function 
        | hd::tl & l -> "Not so empty list" 
        | _ -> "Empty list" 
    
  • を書きます。

+0

ええ、以前は部分的なアクティブパターンの警告が見えました。それは実際には意味をなさないが、アクティブなパターンはコンパイルされた関数であり、マクロではないので、コンパイラはマッチの完全性を静的に検証することはできない。さて、 'inline'キーワードを使ってアクティブなパターンを定義する方法があれば、これは別の話かもしれません。 – luksan

+1

'inline'をアクティブパターンで使うことができます:' let inline(| Empty | _ |)xs = xsと[] - > Some()| _ - > None'と表示されますが、警告はまだ表示されています。 – pad

+0

私はあなたが正しいと思います。私が '<@@ function [] - > Some()| _ - > None @@> '一致式のASTは単にif/elseなので、パターン情報はまだ失われています。 – luksan

4

は、私はあなたがコンパイラの決定手順が十分に強力ではありません(when句と部分的にアクティブパターンとは別に)、別のケースを発見したと思います。 (そのため、警告メッセージはと表示されます:-))。

警告なしで同じ機能を使用する場合は、このような完全なアクティブパターンを使用できます(実際はリストの場合は、@ padが示すように空のリストの場合はおそらく_となります) :

let (|Empty|NonEmpty|) l = 
    match l with [] -> Empty | x::xs -> NonEmpty(x, xs, l) 

let foo = function 
    | Empty -> 0 
    | NonEmpty(x, xs, l) -> 1 
+0

"表示するかもしれません"と言っていますが、 "不完全ではないかもしれない"と "不完全である"とも言われていますので多少あいまいです。 – luksan

関連する問題