2011-02-17 75 views
2

這是我到目前爲止有:F#匹配問題

type u = {str : string} //some type that has some property str (for simplicity, only one) 
type du= 
    | A of u 
    | B of u // some discriminated union that carries u with it 

然後,帶我去的杜的序列我做distinctBy並做不同的是海峽財產。 最好我能想出是這樣的:

Seq.distinctBy (fun d -> match d with (A u|B u) -> u.str) 

代碼工作,但我不喜歡以匹配識別聯合a和b,願與東西來取代了比賽。

問題是,是什麼? :)

編輯:

在我的情況下,與識別聯合的B就始終貫徹同樣的U型與他們,一個解決方案是擺脫杜,並添加它的字符串形式輸入u和簡化這整個混亂,但我想現在保持這種方式,因爲我打算做的比賽,這樣的a和b ...

+2

我相信歧視的工會案件必須是大寫 - 不知道爲什麼這是。 – Jimmy 2011-02-17 22:53:45

+0

@Jimmy,你說的對,我會編輯它,謝謝 – Alex 2011-02-18 15:47:10

回答

5

如何做一個匹配時間的杜的屬性?

type u = {str : string} 

type du = 
    | A of u 
    | B of u with 
    member this.U = 
     match this with 
     (A u | B u) -> u 

[A {str="hello"}; B {str="world"}; A {str="world"}] 
|> Seq.distinctBy (fun x -> x.U.str) 

//val it : seq<du> = seq [A {str = "hello";}; B {str = "world";}] 

但是,我有一些想法,可能會模型之間的關係和更好,同時滿足您的「編輯」的關注。一種方法是簡單地使用元組:

type u = {str : string} 

type du = 
    | A 
    | B 

//focus on type u 
[A, {str="hello"}; B, {str="world"}; A, {str="world"}] 
|> Seq.distinctBy (fun (_,x) -> x.str) 
//val it : seq<du * u> = seq [(A, {str = "hello";}); (B, {str = "world";})] 

//focus on type du 
let x = A, {str="hello"} 
match x with 
| A,_ -> "A" 
| B,_ -> "B" 
//val it : string = "A" 

另一種方式是圍繞杜切換,並添加到u:

type du = 
    | A 
    | B 

type u = { case : du; str : string} 

//focus on type u 
[{case=A; str="hello"}; {case=B; str="world"}; {case=A; str="world"}] 
|> Seq.distinctBy (fun x -> x.str) 
//val it : seq<u> = seq [{case = A; 
//      str = "hello";}; {case = B; 
//           str = "world";}] 

//focus on type du 
let x = {case=A; str="hello"} 
match x with 
| {case=A} -> "A" 
| {case=B} -> "B" 
//val it : string = "A" 
2

你真的不能簡化它像你描述的那麼多,但你可以簡化它。 謝謝@Tomas Petricek

[ A { str = "A" }; B { str = "B" }; B { str = "B" } ] 
|> Seq.distinctBy (fun (A u | B u) -> u.str) 
|> Seq.toArray;; 

輸出

[| A {str = "A";}; B {str = "B";} |] 
+3

你可以用`fun(A u | B u)`而不是`function A u | B u` :-) – 2011-02-18 00:13:29

+0

@Tomas - 哦F#你什麼時候會停止讓我驚訝? – ChaosPandion 2011-02-18 00:28:33

2

我是一個有點新的F#但希望這會有所幫助。在我看來,主動模式可能會讓你的生活更輕鬆,試圖減少你需要輸入模式匹配的內容。而不是使用A a | B b你可以使用有效模式AorB。

type u = { str : string } 

type du = 
    | A of u 
    | B of u 

let (|AorB|) (v:du) = 
    match v with 
     | A a -> a 
     | B b -> b 

[A { str = "A" }; B { str = "B"}; A { str = "A"}] 
    |> Seq.distinctBy (fun d -> 
        match d with 
         | AorB s -> s) 
    |> Seq.iter (fun i -> match i with AorB c -> printfn "%s" c.str) 

隨着斯蒂芬的加入,最終的表達式可以這樣寫。

[A { str = "A" }; B { str = "B"}; A { str = "A"}] 
|> Seq.distinctBy (|AorB|) 
|> Seq.iter (fun i -> match i with AorB c -> printfn "%s" c.str)