3

F# でアクティブ パターンを定義して使用する方法 (部分アクティブ パターンや、さまざまな種類の使用可能なパターンを含む) を理解しています。例えば

let (|Big|Small|) animal = if animal.IsBig then Big(animal) else Small(animal)
let f = function | Big(_) -> "big" |Small(_) -> "small

letただし、バインド、引数、およびその他の場所でのアクティブ パターンと識別共用体の使用については混乱しています。たとえば、MSDN には次のコードがあります。

let GetSubstring1 (Slice(p0, p1, text)) = 
    printfn "Data begins at %d and ends at %d in string %s" p0 p1 text
    text.[p0..p1]

これは私を少し混乱させます。

特定の問題。私が差別された組合を持っているとしましょう、

type Union = A of int * int | B of int

Union.Aどうにかして のみを受け入れる関数を作成できますか?

let f (A(a, b)) = a + b

この状況では、一致しないパターンがあることがわかります。それを満たす方法はありますか?

4

1 に答える 1

8

@ildjarn が指摘したように、これはすべてのパターンに適用されます。それらは、match句の場合 (およびfunctionwhich は類似しています) に表示される可能性がありますが、letバインドされた関数のパラメーター宣言やlet値バインディングにも表示されます。

主な違いは、では常に成功する完全なletパターンのみを使用することです。複数の句があるため、これはorには必要ありません。そのため、最初の句が失敗した場合、マッチングを続行して次の句を試すことができます。matchfunction

たとえば、次の完全なパターンはint、それを として受け取り、返しますstring

let (|AsString|) (n:int) = n.ToString()

使用方法は次のとおりです。

let (AsString s) = 42         // Defines a value 's' of type string
match 3 with AsString s -> s  // Returns a value "3" of type string
let convert (AsString s) = s  // Defines a function 'int -> string'
let convert = function AsString s -> s  // Same as the previous line

編集: 2 番目の質問に答えるにletは、不完全なパターン (つまり、識別された共用体の 1 つのケースのみを受け入れる) で使用すると、コンパイラの警告が表示され、実行時にコードが失敗する可能性があります (他の識別されたもので呼び出す場合)ユニオンケース):

let f (A(a, b)) = a + b      // This gives compile-time warning
f (B 42)                     // This will fail at runtime 

いずれかのケースでのみ機能する関数を定義する必要がある場合は、別の型を定義する必要があります。

type AInfo = int * int 
type Union = A of AInfo | B of int  

次に、受け取るだけの関数を作成できます(ただし、両方のオプションが有効な入力を表す場所でAInfo作業することはできます)。Union

于 2012-10-04T23:17:05.457 に答える