2017-05-16 7 views
2

F#の次を考えるタイプマッチングとアクティブパターン

let texture (f : IFruit) = 
    match f with 
    | :? Avocado as a -> if a.age < 7 then "firm" else "mushy" 
    | _ -> String.Empty 

...ではなく、この:

type IFruit = interface end 

type Avocado = { color : string; age : int } interface IFruit 

let (|AvocadoTexture|) (a : Avocado) = if a.age < 7 then "firm" else "mushy" 

が...なぜこの仕事をしますか?

let texture (fruit : IFruit) = 
    match fruit with 
    | AvocadoTexture t -> t // "The type IFruit does not match the type Avocado" 
    | _ -> String.Empty 

答えて

6

fruit任意IFruitとすることができるが、AvocadoTextureアクティブパターンのみaの型注釈の通り、特定の実施Avocadoを受け入れてもよいです。 あなたはアクティブパターンがどのIFruitを受け入れるが、唯一のAvocadoするための有用な値を返すようにしたい場合は、あなたがそれを部分を行うことができます。あなたが望んでいたよう

let (|AvocadoTexture|_|) (f : IFruit) = 
    match f with 
    | :? Avocado as a -> 
     if a.age < 7 then "firm" else "mushy" 
     |> Some 
    | _ -> None 

を今すぐあなたのtexture機能が動作します:

let texture (fruit : IFruit) = 
    match fruit with 
    | AvocadoTexture t -> t 
    | _ -> String.Empty 
+1

ありがとうございます!部分アクティブパターンは私が必要としたものです。 – MiloDC

2

パーシャルアクティブパターンとアクティブパターンがあることに留意してください。アクティブパターンには、7つのタグがあり、具体的に何かを照合することができます。どちらの形式も便利です。

アクティブパターンは、余分なものが必要と判断した後で、ケースを処理しなかったすべての場所をコンパイラに伝えたい場合に適しています。コンパイラは、警告を表示するのではなく、エラーとして警告するように設定することができます。

open System 

type IFruit = interface end 

type Avocado = 
    { color : string; age : int } 
    interface IFruit 
    static member tryFromIFruit(x:IFruit) = 
    match x with 
    | :? Avocado -> Some(x:?>Avocado) 
    | _ -> None 

let (|Firm|Mushy|) (a : Avocado) = if a.age < 7 then Firm else Mushy 

let texture (fruit : IFruit) = 
    match fruit |> Avocado.tryFromIFruit with // we're not sure if it's an Avocado. 
    | Some(Firm) -> "firm"      // use Some(SomethingElse()) when you want to collapse an extra layer of "match" statements. 
    | Some(Mushy) -> "mushy" 
    | None -> "" 

texture ({ color = "green"; age = 4 } :> IFruit) 

ドキュメント:https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/active-patterns

関連する問題