简体   繁体   English

F#匹配问题

[英]F# match question

this is what i have so far: 这是我到目前为止:

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

then, somewhere i have a sequence of du that i am doing distinctBy and the property to do distinct is str. 然后,在某个地方,我有一个du序列,我正在做distinctBy和属性做的不同是str。 best i could come up with is this: 我能想出的最好的是:

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

the code works, but i don't like having to match on a and b of the discriminated union and would like to replace the match with something. 代码有效,但我不喜欢在受歧视的联盟的a和b上匹配,并希望用某些东西替换匹配。

question is, what? 问题是什么? :) :)

EDIT: 编辑:

in my case, a and b of the discriminated union will always carry same type u with them, one solution is to get rid of du and add it's string form to type u and simplify this whole mess, but i would like to keep it this way for now because i was going to do matches and such on the a and b... 在我的情况下,被区分的联合的a和b将总是带有相同的类型u,一个解决方案是摆脱du并添加它的字符串形式来输入u并简化整个混乱,但我想保留它现在的方式,因为我打算在a和b上做匹配...

How about doing the match one time as a property of du? 作为du的财产,这次比赛怎么样?

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";}]

However, I have a couple ideas which may model the relationship between u and du better while satisfying your "EDIT" concerns. 但是,我有一些想法可以更好地模拟你和你之间的关系,同时满足你的“编辑”问题。 One way is simply using tuples: 一种方法是简单地使用元组:

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"

Another way is to switch it around and add du to u: 另一种方法是切换它并将du添加到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"

You really can't simplify it as much as you describe but you can simplify it. 你真的不能像你描述的那样简化它,但你可以简化它。 Thanks @Tomas Petricek 谢谢@Tomas Petricek

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

Output 产量

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

I'm a bit new to F# but hopefully this will help. 我对F#有点新鲜,但希望这会有所帮助。 It seems to me that Active Patterns might make your life easier in trying to cut down what you need to type in your pattern matching. 在我看来,Active Patterns可能会让您的生活更轻松,以减少您在模式匹配中输入的内容。 Instead of using A a | 而不是使用A a | B b you can use the active pattern AorB in it's place. 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)

With Stephen's addition the final expression can be written thusly. 随着斯蒂芬的加法,最后的表达可以这样写出来。

[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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM