模式匹配是否是获取与联合用例关联的数据的唯一方法



假设你有这样一个并集:

type Thing = 
| Eagle
| Elephant of int

你的代码有一个大象列表,如

let l = [Elephant (1000); Elephant (1200)]

您想迭代l,并打印出与每个Elephant相关的数据。有没有一种不使用模式匹配的方法?

在您的示例中,您说您有一个大象列表-这在本例中是正确的-但l的类型实际上是Thing值的列表,因此它可以包含大象和鹰。这就是为什么你需要使用模式匹配-来处理所有可能的情况。

如果您经常需要使用只包含大象的list,那么定义一个单独的大象类型可能是有意义的。比如:
type ElephantInfo = { Size : int }
type Thing = 
  | Elephant of ElephantInfo
  | Eagle

现在你可以创建一个list<ElephantInfo>类型的列表,它可以只包含大象,所以你不需要模式匹配:

let l1 = [ {Size=1}; {Size=2} ]
for el in l1 do printfn "%d" el.Size

另一方面,如果你想混合大象和鹰,你将创建list<Thing>,然后使用模式匹配:

let l2 = [ Elephant {Size=1}; Eagle ]

你可以这样做:

l
|> List.collect (function Elephant x -> [x] | _ -> [])
|> List.iter (printfn "%i")

打印

1000
1200

它仍然使用模式匹配,但它是相当少的。

您当然可以选择完全象牙塔 (®斯科特Wlaschin)

如about:

type Thing = 
 | Eagle
 | Elephant of int
type MaybeElephantBuilder() =      
 member this.Bind(x, f) = 
  match x with
  | Eagle -> 0
  | Elephant a -> f a
 member this.Return(x) = x
let maybeElephant = new MaybeElephantBuilder()
let l = 
 [ Elephant(1000)
   Elephant(1200)
    ]
let printIt v = 
 let i = 
  maybeElephant { 
   let! elephantValue = v  
   return elephantValue
  }
 printfn "%d" i   
l |> Seq.iter printIt

它甚至可以处理老鹰扔进去的东西!

嗯…

删除非鹰,代码将飞行…

let l = 
 [ Eagle
   Leadon
   Elephant(1000)
   Eagle
   Meisner
   Elephant(1200)
   Eagle
   Felder
    ]
l |> Seq.iter printIt

但没有。这不太好。它不短。它更多的是为了好玩(如果有的话!)。这可能也是对f#计算表达式最糟糕的误用!

你的将需要模式匹配的地方。

Thx斯科特!和Petricek。

计算表达式动物园的真实!: -)

您可以使用Microsoft.FSharp.Reflection Namespace的反射,但它更麻烦,更慢。

模式匹配可能是从区别并集中获取数据的最简单方法。

(你也有一个Things的列表,它的所有成员恰好是Elephant的联合情况)。

有一种方法可以将模式匹配放置到函数的头中(或let绑定)。尽管如此,它仍然是一个模式匹配。

// This function takes a tuple:
// the first argument is a Thing,
// the second is "default" weight to be processed if the first one is NOT an Elephant
let processElephant (Elephant weight, _ | _, weight) =
    weight
let [<Literal>] NON_ELEPHANT_WEIGHT = -1
// usage:
let totalWeight =
    [Elephant (1000); Elephant (1200)]
    |> List.sumBy (fun el -> processElephant(el, NON_ELEPHANT_WEIGHT))

这个问题及其答案提供了更多的细节

最新更新