首页 > 解决方案 > F#如何避免两次施法

问题描述

情况1

  1. 取元素 while is Some value from sequense
  2. 打印一些值
let a = seq { yield Some 1; yield Some 2; yield Some 3; yield None }

a
|> Seq.takeWhile Option.isSome // cast 1
|> Seq.map Option.get          // cast 2
|> Seq.iter (printfn "%A")

案例2

  1. 过滤一些值的序列
  2. 打印 Some 的值
a
|> Seq.filter Option.isSome    // cast 1
|> Seq.map Option.get          // cast 2
|> Seq.iter (printfn "%A")

案例3

  1. 按类型按元素分组
  2. 打印每组的值
type AB =
    | A of a : int
    | B of b : string

let a = seq{
    yield A 1
    yield A 2
    yield B "ds"
    yield B "fsdf"
}

let (|As|Bs|) = function
    | A _ -> As
    | B _ -> Bs

let matcher = function
    | A a-> printfn "%A" a
    | B b -> printfn "%A" b

a
|> Seq.groupBy (|As|Bs|)       // cast 1
|> Seq.map snd
|> Seq.iter (Seq.iter matcher) // cast 2

为什么我需要避免双重铸造?

标签: castingf#pattern-matchingseq

解决方案


对于“案例 2”,您可以使用Seq.choose身份功能,id

a
|> Seq.choose id
|> Seq.iter (printfn "%A")

文档Seq.choose说_ _

将给定函数应用于列表的每个元素,并返回包含每个元素的结果的列表,其中函数返回 Some 和一些值。

因此,将标识函数传递给它将返回每个Option值的内容Some


推荐阅读