将计算表达式值列表评估为相应的值列表的好方法是什么?
假设我的计算表达式类型为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)
}
还有更简洁的方法吗?
答案 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 }
但是除了累加器和一些小的语法差异外,它与您的几乎相同!