F#中的选项列表中的选项列表

时间:2018-10-27 21:24:11

标签: f#

给出一个列表[Some 1;一些2; Some 3]我想要一个输出Some [1; 2; 3]。给定一个列表[Some 1; None]应该产生None

我是F#的初学者,到现在为止,我已经完成了这两个操作,并创建了一个列表选项。我如何制作一个选项列表以通过此功能获得结果?

let lift a b =
    match a, b with
    | Some av, Some bv  -> Some[av;bv]
    | _, _ -> None

lift (Some 2) None

3 个答案:

答案 0 :(得分:3)

let lift l = 
    if List.contains None l then None
    else Some (List.map Option.get l)

答案 1 :(得分:3)

在功能世界中,您所描述的通常称为sequence。 它是围绕通用类型的顺序交换的概念:

  • List<Option<int>>Option<List<int>>

这是一种通用的方法:

module Option =
    let (>>=) r f = Option.bind f r
    let rtn v     = Some v

    let traverseList f ls = 
        let folder head tail = f head >>= (fun h -> tail >>= (fun t -> h::t |> rtn))
        List.foldBack folder ls (rtn List.empty)
    let sequenceList   ls = traverseList id ls

    // val traverseList : ('a -> 'b option) -> 'a list -> 'b list option
    // val sequenceList : 'a option list -> 'a list option

此处sequenceList的类型签名为'a option list -> 'a list option,也可以表示为List<Option<'a>> -> Option<List<'a>>。正是您想要的。

但是,但是,但是...与其他答案相比,这个答案似乎更加复杂。有什么意义?

重点是该解决方案是通用的,可以应用于任何单子(或适用性)类型。例如,与Option类似的通用类型为Result,解决方案与以前几乎相同:

module Result =
    let (>>=) r f = Result.bind f r
    let rtn v     = Ok v

    let traverseList f ls = 
        let folder head tail = f head >>= (fun h -> tail >>= (fun t -> h::t |> rtn))
        List.foldBack folder ls (rtn List.empty)
    let sequenceList   ls = traverseList id ls

    // val traverseList : ('a -> Result<'b,'c>) -> 'a list -> Result<'b list,'c>
    // val sequenceList : Result<'a,'b> list -> Result<'a list,'b>

看到了吗?除了第2行和第3行,其余都相同。

这使您可以抽象概念并将其放在脑海中。将来,当您进行编程时,这会发生很多次,您需要遍历泛型类型,而这些类型最终会根据您的需求而倒置。

但是没有必要重新发明轮子。掌握了如何创建sequence(和traverse)的知识后,您可以随时进入工具包,并在需要任何单数或应用类型时将其拉出,无论AsyncResultOption

如果您想深入了解,请访问此网站,其中用清晰的图形和示例解释了这些概念:https://fsharpforfunandprofit.com/posts/elevated-world-4/

答案 2 :(得分:-1)

也许还有一些惯用的方法-使用模式匹配,序列和identity function

let lift options =
    match options |> Seq.contains None with
    | true -> 
        None
    | false ->
        options
        |> Seq.choose id 
        |> Some