要使列表推导并行运行,很容易添加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
...