[英]N-dimensional Array with Haskell
在 Python 中,我們可以使用元組創建索引numpy.ndarray
,例如
cube = numpy.zeros((3,3,3,))
print(cube[(0,1,2,)])
. 然而,在 Haskell 中,要索引一個多層數組,這只能用多個!!
's 這似乎非常臨時。
我試過foldl
:
foldl
(!!)
[[[1, 2, ....], [1, 2, ....], [1, 2, ....]],
[[1, 2, ....], [1, 2, ....], [1, 2, ....]],
[[1, 2, ....], [1, 2, ....], [1, 2, ....]]]
[0, 1, 2]
然而foldl
只能應用於a -> b -> a
類a -> b -> a
函數,而不是[a] -> b -> a
。 其他一些信息顯示hmatrix
可以在 python 中執行類似numpy
的操作,但它僅適用於維度不可調整的矩陣和向量。
這總是可以用 C 風格的索引來完成,即將所有數據放在一個 1d 列表中,並用乘法索引它們, 0 + 1*3 + 2*9
,但它看起來很粗魯,丟失了維度信息並且會導致編譯器不能按正確的順序調整它們。
如何以更抽象的方式做到這一點?
從你想要實現的問題中我不太清楚,但如果你的問題只是關於在 Haskell 中索引多維數組,那么我會盡力回答它。 感謝 @leftaroundabout 在評論部分建議massiv
,作為該庫的作者,我傾向於同意他的評論。
有一件事是肯定的,出於多種原因,您不想將嵌套列表用於數組目的。 線性索引的復雜性和糟糕的性能只是其中一些原因。
讓我們看看如何使用massiv
來完成它。 首先,我將翻譯您的numpy
示例:
cube :: Array P Ix3 Float
cube = A.replicate Seq (Sz (3 :> 3 :. 3)) 0
請注意,因為我們實際上在 Haskell 中有類型,所以我們需要對我們嘗試構造的數組類型進行一些注釋,例如。 裝箱與未裝箱、可變與不可變等。我建議通讀圖書館的文檔以獲得有關這些主題的更多信息。 在這里,我將專注於指數,因為這就是問題所在。 為了從上述 3D 數組中的第 0 頁、第 2 行和第 3 列( numpy
示例中的cube[(0,1,2,)]
獲取元素,我們可以使用O(1)時間運算符!
在其右側提供索引:
λ> cube ! (0 :> 1 :. 2)
0.0
請注意索引運算符!
是部分的,將導致運行時異常越界:
λ> cube ! (10 :> 1 :. 2)
*** Exception: IndexOutOfBoundsException: (10 :> 1 :. 2) is not safe for (Sz (3 :> 3 :. 3))
CallStack (from HasCallStack):
throwEither, called at src/Data/Massiv/Core/Common.hs:807:11 in massiv-1.0.1.0-...
哪個可以通過其更安全的變體輕松避免!?
:
λ> cube !? (0 :> 1 :. 2) :: Maybe Float
Just 0.0
λ> cube !? (10 :> 1 :. 2) :: Maybe Float
Nothing
與numpy
,可以使用元組來索引massiv
數組,但由於元組是多態的,類型檢查器有時會更棘手地推斷出正確的東西,而且在massiv
最多支持 5 維的元組。 這就是為什么我將展示Ix n
類型的示例,其中n
是維數,可以是任意的。
使用平面向量時,使用常規Int
進行索引(對應於Ix 1
):
λ> let vec = makeVectorR P Seq (Sz 10) id
λ> vec
Array P Seq (Sz1 10)
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
λ> vec ! 7
7
對於二維,有一個特殊的運算符:.
(對應於Ix 2
):
λ> let mat = makeArrayR P Seq (Sz (2 :. 10)) $ \(i :. j) -> i + j
λ> mat
Array P Seq (Sz (2 :. 10))
[ [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
, [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
]
λ> mat ! (1 :. 3)
4
任何大於 2 的維度的索引都使用:>
運算符構建(對應於Ix n
):
λ> let arr3D = makeArrayR P Seq (Sz (3 :> 2 :. 1)) $ \(i :> j :. k) -> i + j + k
λ> arr3D ! (2 :> 1 :. 0)
3
λ> let arr4D = makeArrayR P Seq (Sz (4 :> 3 :> 2 :. 1)) $ \(h :> i :> j :. k) -> h + i + j + k
λ> arr4D ! (3 :> 2 :> 1 :. 0)
6
可以在自述文件的#index部分中找到有關帶有示例的索引的更多信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.