【问题标题】:List of option to a option list in F#F#中选项列表的选项列表
【发布时间】:2018-10-27 21:24:11
【问题描述】:

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

我是 F# 的初学者,直到现在我已经完成了两个选项并创建了一个列表选项。我怎样才能制作一个选项列表来通过这个函数来得到结果?

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

lift (Some 2) None

【问题讨论】:

    标签: f#


    【解决方案1】:

    在您所描述的功能世界中,通常称为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)的知识后,您可以在任何一元类型或应用类型需要时将其伸入工具包中,无论是AsyncResult、@ 987654336@等

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

    【讨论】:

    • 非常感谢您的详细解答。现在我很清楚了:)
    【解决方案2】:
    let lift l = 
        if List.contains None l then None
        else Some (List.map Option.get l)
    

    【讨论】:

      猜你喜欢
      • 2019-04-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-03
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-13
      相关资源
      最近更新 更多