Если у меня есть функция, которая выполняет четыре очень длинных вычисления и возвращает список с результатом четырех вычислений, но где каждое вычисление не зависит от другого, как вы «распараллеливаете» это в Haskell?
Чтобы лучше объяснить мой вопрос, вот пример Clojure того, что я имею в виду:
(defn some-function [arg1 arg2 arg3 arg4]
let [c1 (very-long-computation arg1)
c2 (very-long-computation arg2)
c3 (very-long-computation arg3)
c4 (very-long-computation arg4)]
[c1 c2 c3 c4])
Вы можете создать три дополнительных потока, например:
(defn some-function [arg1 arg2 arg3 arg4]
let [c1 (future (very-long-computation arg1))
c2 (future (very-long-computation arg2))
c3 (future (very-long-computation arg3))
c4 (very-long-computation arg4)] ; no need to wrap c4 in a future
[@c1 @c2 @c3 c4])
Будет ли эквивалентно следующее в Haskell?
someFunction :: (a -> a -> a ->a) -> [a]
do c1 <- rpar (very-long-computation arg1)
c2 <- rpar (very-long-computation arg2)
c3 <- rpar (very-long-computation arg3)
c4 <- (very-long-computation arg4)
rseq c1
rseq c2
rseq c3
return (c1, c2, c3, c4)
Нужно ли rpar/rseq c4?
Подходит ли rpar/rseq для таких параллельных вычислений?
Что, если я не rseq, будет ли программа ждать позже, когда я попытаюсь получить доступ к возвращаемым значениям внутри возвращаемого списка?
Является ли это прозрачным или вам нужно сделать что-то вроде «deref», которое происходит в Clojure, когда вы используете «@»?