簡體   English   中英

使用 Haskell 的 N 維數組

[英]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 -> aa -> 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM