タスク並列ライブラリを使用してツリーを合計しようとしています。このライブラリでは、ツリーが特定の深さまでトラバースされるまで子タスクが生成されます。それ以外の場合は、スタックオーバーフローを回避するために、継続パススタイルを使用して残りの子ノードが合計されます。
ただし、コードはかなり醜いように見えます。状態モナドを使用して現在の深さを運ぶのは良いことですが、状態モナドは末尾再帰ではありません。または、州を持ち歩くために継続モナドをどのように変更しますか?または、状態モナドと継続モナドの組み合わせを作成しますか?
let sumTreeParallelDepthCont tree cont =
let rec sumRec tree depth cont =
let newDepth = depth - 1
match tree with
| Leaf(num) -> cont num
| Branch(left, right) ->
if depth <= 0 then
sumTreeContMonad left (fun leftM ->
sumTreeContMonad right (fun rightM ->
cont (leftM + rightM )))
else
let leftTask = Task.Factory.StartNew(fun () ->
let leftResult = ref 0
sumRec left newDepth (fun leftM ->
leftResult := leftM)
!leftResult
)
let rightTask = Task.Factory.StartNew(fun () ->
let rightResult = ref 0
sumRec right newDepth (fun rightM ->
rightResult := rightM)
!rightResult
)
cont (leftTask.Result + rightTask.Result)
sumRec tree 4 cont // 4 levels deep
このブログ投稿についてもう少し詳しく説明します:http://taumuon-jabuka.blogspot.co.uk/2012/06/more-playing-with-monads.html