seg*_*uso 3 f# ocaml functional-programming
这个问题是关于函数式编程的.示例代码在F#中.
假设我有一个简单的函数f:
let f x =
x + 1
Run Code Online (Sandbox Code Playgroud)
现在(由于我不想解释,与线程相关的原因)我必须将f转换为具有continuation的函数:
let f x cont =
cont (x+1)
Run Code Online (Sandbox Code Playgroud)
现在我必须重写所有调用f的函数,这些函数将不再编译.
例如,如果我有这个功能
let g x =
let res = f x
res + 2
Run Code Online (Sandbox Code Playgroud)
我必须重写g as
let g x cont =
f x (fun res ->
cont (res + 2) )
Run Code Online (Sandbox Code Playgroud)
这已经变得复杂了,但仍然是可以管理的.
但问题是:如何重写以下代码?
let lmapped = [ for x in l do
let res = f x
yield res + 1 ]
if List.isEmpty lmapped then
...
Run Code Online (Sandbox Code Playgroud)
有没有一种简单的方法来重写它?(可能避免使用显式递归函数,例如"let rec ...")谢谢
使用显式延续传递样式编写代码会很快变得难看.
在这种情况下,您需要编写基于continuation的List.map函数版本:
let map f list cont =
let rec loop acc list cont =
match list with
| [] -> cont (List.rev acc) // Reverse the list at the end & call continuation!
| x::xs -> f x (fun x' -> // Call `f` with `cont` that recursively calls `loop`
loop (x'::acc) xs cont )// Call `loop` with newly projected element in `acc`
loop [] list cont
Run Code Online (Sandbox Code Playgroud)
原则上,这只是一个"简单的句法转换",可以"自动"完成,但很难做到这一点而不会迷路!
该函数实际上只是一个map具有内部loop函数的普通函数,它递归地遍历输入列表并调用f以进行投影.除了所有函数都采用附加参数cont并通过最后调用返回结果cont.这也是f传递给map 的函数的情况!看到:
map (fun n cont -> cont (n * 2)) [1 .. 10] (printfn "%A")
Run Code Online (Sandbox Code Playgroud)
如果你大量使用continuation,那么编写计算构建器(也就是monad)来处理continuation可能更容易.这不太适合单个StackOverflow的答案,但请看Brian McNamara的这篇优秀文章