2011-02-17 99 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)