Haskell:并行do与列表推导式



要使列表推导并行运行,很容易添加using parList rdeepseq,但是如果列表推导使用do符号表示呢?

例如,这段代码可以很好地并行运行。

entry n = [ (rowSet,finalEV rowSet,rrDone rowSet,oneRRLeft rowSet,twoRRLeft rowSet) | rowSet <- getChoiceList 13 n] `using` parList rdeepseq
where
prevFinal = getFinalEVNEW $ entry (n-1)

rrDone rowSet = (getRRDoneNEW prevFinal rowSet)

doneStripped rowSet = map ((v,_,ev) -> (v,ev)) (rrDone rowSet)
oneRRLeft rowSet = getRRChoicesNEW (doneStripped rowSet)

oneRRStripped rowSet = map ((v,_,ev) -> (v,ev)) (oneRRLeft rowSet)
twoRRLeft rowSet = getRRChoicesNEW (oneRRStripped rowSet)

twoRRStripped rowSet = map ((v,_,ev) -> (v,ev)) (twoRRLeft rowSet)
finalEV rowSet = weightedEV theProbs (twoRRStripped rowSet)

但是用do表示法表示时更容易阅读。上面的部分,以do的形式表达,并结合更广泛的背景,变成:

monster :: [[([Bool],Double,[([Int],Int,Double)],[([Int],[Bool],Double)],[([Int],[Bool],Double)])]]
monster = [ entry i | i <- [0..13] ]
where
entry 0 = [(replicate 13 False,0,[],[],[])]

entry n = go ( getFinalEVNEW ( entry (n-1) ) )
where
go prevFinal = do 

rowSet <- (getChoiceList 13 n )

let rrDone = (getRRDoneNEW prevFinal rowSet)
let doneStripped = map ((v,_,ev) -> (v,ev)) rrDone
let oneRRLeft = getRRChoicesNEW doneStripped

let oneRRStripped = map ((v,_,ev) -> (v,ev)) oneRRLeft
let twoRRLeft = getRRChoicesNEW oneRRStripped

let twoRRStripped = map ((v,_,ev) -> (v,ev)) twoRRLeft
let finalEV = weightedEV theProbs twoRRStripped

return (rowSet,finalEV,rrDone,oneRRLeft,twoRRLeft)

但不清楚如何使do形式并行运行。

是否有一种直接的方法将并行列表理解转换为等效的do形式?

编辑:"做版本";根据上下文略加扩展

一个相关的问题是算法是递归的,任何并行化entry n的尝试都应该等到entry (n-1)处于正常形式。对吧?

这是一个类似于Yahtzee的游戏的解的计算。这是"让我们学习haskell"。锻炼。

您所说的工作代码的直接翻译如下:

entry n = go ( getFinalEVNew ( entry (n-1) ) ) `using` parList rdeepseq

如果您坚持将using子句附加到do块,您可以使用括号:

go prevFinal = (do
...
) `using` parList rdeepseq

或者在where块和do块之间使用缩进级别:

go prevFinal = do
...
`using` parList rdeepseq

或在前缀

中应用using
go prevFinal = (`using` parList rdeepseq) $ do
...

最新更新