是否有标准的F#defaultArg实现接受懒惰?

时间:2016-04-30 11:09:06

标签: f#

我需要defaultArg函数的实现,Lazy作为第二个参数。这是一个用法示例:

defaultArgLazy option (lazy doSomeHeavyWorkThatShouldBeAvoided())

它很容易实现

let defaultArgLazy o (p:'a Lazy) = 
  match o with 
  | Some v -> v 
  | None -> p.Force()

但我想知道是否有一个我缺失的标准实施。

2 个答案:

答案 0 :(得分:1)

我不知道内置的任何内容,但这是您的功能的更通用版本:

module Option =
    let lazyDefault f opt =
        match opt with
        | Some x -> x
        | None -> f()

let lazyVal = lazy 1
let opt = None

opt |> Option.lazyDefault lazyVal.Force  // returns 1

它需要(unit -> 'a)的任何功能,而不是具体的Lazy<'a>',因此您只需通过Lazy的Force方法,并保留评估仅发生的保证一次。

在.NET现有的Lazy.Force()之上,可能会在F#中添加Lazy.Value,以便您可以更高效地使用更高阶函数。

请注意,我已将参数顺序与内置defaultArg进行交换,以便与其他模块中的函数更加一致,更方便管道/曲线。

答案 1 :(得分:1)

如果懒惰值仅在代码的稍后时间点使用,则使用defaultArg并将Lazy<'a> option作为第一个参数传递给它也可能是个主意。这样选择选项或默认参数就会与评估结果时分开。

采取这个想法,功能

let defaultArgLazy opt lazyDef =
  (defaultArg (Option.map Lazy.CreateFromValue opt) lazyDef).Value

会做你想要的 - 就像TheQuickBrownFox那样。