F#如何避免两次投射

Свя*_*лав 0 f# casting pattern-matching seq

情况1

  1. 从序列中获取价值
  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")
Run Code Online (Sandbox Code Playgroud)

情况二

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

情况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
Run Code Online (Sandbox Code Playgroud)

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

  • 保持代码清洁
  • 为了避免引发异常

gle*_*nsl 5

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

a
|> Seq.choose id
|> Seq.iter (printfn "%A")
Run Code Online (Sandbox Code Playgroud)

文档Seq.choose

将给定函数应用于列表的每个元素,并返回由每个元素的结果组成的列表,其中函数返回带有某些值的Some。

传递给它的身份函数将因此返回Optionis 的每个值的内容Some