Допустим, у меня есть простой рекурсивной функцииКонтроллинг массив заполнить Haskell
Z(i,j) = Sum(Z(i, k), k = 0..j-1) + Sum(Z(k, j), k = 0..i-1)
Z(0,0) = 1
Если вы кладете это в таблице, с (0,0) в левом нижнем углу и (I, J) на в верхнем правом углу вы можете видеть, что в целом все ячейки зависят только от каждой из ячеек слева и внизу, а диагонали сверху вниз и внизу справа могут быть вычислены параллельно.
Для языка как C, я мог бы реализовать динамическую заливку программирования, начиная с нижнего левого и работает мой путь вверх по столбцам:
// for Z[n][m]
for(i = 0; i <= n; i++) {
for(j = 0; j <= m; j++) {
for(k = 0; k < j; k++) {
Z[i,j] += Z(i, k)
}
for(k = 0; k < i; k++) {
Z[i,j] += Z(k, j)
}
}
}
Если бы я хотел распараллелить это, я мог бы просто собрать индексы диагонали, которые в настоящее время работают, а затем отправляют соответствующую функцию по каждому из индексов.
В Haskell я мог бы сделать что-то вроде:
z = array ((0,0), (10,10))
[((i, j), 1 + (sum (map (\x -> z ! (i, x)) [0..j-1])) +
(sum (map (\x -> z ! (x, j)) [0..i-1]))) | i <- [0..10], j <- [0..10]]
Есть несколько вещей, которые я не люблю об этом. 1: сложнее читать и менее ясно, что происходит. 2: Я не контролирую порядок исполнения. Как узнать, может ли Haskell заполнять массив наиболее эффективным способом? Есть ли способ реализовать это в Haskell, так что он легко читается, и я контролирую вычислительный поток?