评估计算表达式值的列表

时间:2018-11-12 04:24:52

标签: f#

将计算表达式值列表评估为相应的值列表的好方法是什么?

假设我的计算表达式类型为M<a>,那么我想知道什么是编写函数的最佳方法:

mysequence : list<M<'a>> -> M<list<'a>>

我可以递归地写出来:

let rec mysequence = function
    | [] -> builder { return [] }
    | (x::xs) -> builder { let! y = x
                           let! ys = mysequence xs
                           return (y::ys)
                         }

还有更简洁的方法吗?

1 个答案:

答案 0 :(得分:4)

使用List.fold可以使此过程更短,如果引入了一些辅助组合器,例如以下类型的lift2函数,则可以使它更短:

lift2 : ('a -> 'b -> 'c) -> M<'a> -> M<'b> -> M<'c>

这是您可以使用builder { .. }表示法轻松定义的东西,它使您可以将对普通值起作用的函数转换为对包装值起作用的函数。然后,您可以取消列表编辑操作并将其与fold一起使用。这样做会使代码更短(如果您忽略了一个人必须编写的所有帮助程序),但这也使它变得丑陋和晦涩难懂。

如果我正在写这篇文章,我会选择与您的版本非常接近的东西。我宁愿将整个正文保留在builder { .. }中,而不要使用function,而且我还要使用accumulator参数,所以我写:

let rec mysequence acc input = builder {
  match input with 
  | [] -> return List.rev acc
  | x::xs -> 
      let! y = x
      return! mysequence (y::acc) xs }

但是除了累加器和一些小的语法差异外,它与您的几乎相同!