使用你的元組的表示形式,並且沒有多少注意泛泛之處,下面是你的問題的一個解決方案。
type Square2 a = ((a,a), (a,a))
type Square3 a = ((a,a,a), (a,a,a), (a,a,a))
extend1 :: Num a => Square2 a -> Square3 a
extend1 ((a,b), (c,d)) =
((a, b, ab )
, (c, d, cd )
, (ac, bd, abcd))
where
ab = a + b
cd = c + d
ac = a + c
bd = b + d
abcd = ab + cd
注意我如何使用這兩種從輸入的模式和where
條款中的定義撲殺變量定義。另請注意,在構建全新輸出的同時,我如何破壞和消耗輸入---一些元素被重用,但結構本身被破壞。最後,請注意我如何選擇元組內部的類型,使其能夠被Num
類型類型常量和約束,從而允許我使用(+)
進行添加。
類似的功能,通用和使用Array
S有像
extend1A :: Num a => Array (Int,Int) a -> Array (Int, Int) a
一個類型,我們已經失去了才知道的Array
S的確切大小的能力,但它表明,我們的函數接受一個Array
一些尺寸並返回另一個Array
,其索引相同並且包含相同的Num
受約束的類型。
array
函數將第一個參數作爲一組邊界。我們需要根據輸入數組
extend1A ary0 = array bounds1 ... where
((minX, minY), (maxX, maxY)) = bounds ary0
(maxX1, maxY1) = (succ maxX, succ maxY)
bounds1 = ((minX, minY, (maxX1, maxY1))
的bounds
更新這些然後array
以「ASSOCS」作爲第二個參數列表。我們可以將任何Array ix a
視爲等同(大致)等同於聯繫人列表[(ix, a)]
,其列出值爲「在索引ix
處的值爲a
」的值。要做到這一點,我們必須知道我們之前管理的ix
類型的bounds
。
要使用舊數據更新數組,我們可以修改舊數組的assocs
以包含新信息。具體而言,這意味着extend1A
看起來有點像
extend1A ary0 = array bounds1 (priorInformation ++ extraInformation) where
priorInformation = assocs ary0
extraInformation = ...
((minX, minY), (maxX, maxY)) = bounds ary0
(maxX1, maxY1) = (succ maxX, succ maxY)
bounds1 = ((minX, minY, (maxX1, maxY1))
如果extraInformation
是空的([]
)然後extend1A ary
將等於ary
上在其範圍的所有外部的輸入ary
和undefined
的範圍內的所有indicies。我們需要填寫extraInformation
加總信息。
extend1A ary0 = array bounds1 (priorInformation ++ extraInformation) where
priorInformation = assocs ary0
extraInformation = xExtension ++ yExtension ++ totalExtension
xExtension = ...
yExtension = ...
totalExtension = ...
((minX, minY), (maxX, maxY)) = bounds ary0
(maxX1, maxY1) = (succ maxX, succ maxY)
bounds1 = ((minX, minY, (maxX1, maxY1))
如果我們認爲延伸在三個陣列中,xExtension
通過ab
和extend1
cd
標記,所述yExtension
通過extend1
ac
和bd
標記和extend1
標記由abcd
那麼我們就可以計算各個所述totalExtension
部分依次。
totalExtension
是最容易的 - 它只是priorInformation
中每個(i,a)
對的「值分量」的總和。它也可能是xExtension
或yExtension
的「價值組成部分」的總和,但爲了儘可能顯得正確,我們將選擇第一個選項並將其安裝在右下角。
extend1A ary0 = array bounds1 (priorInformation ++ extraInformation) where
priorInformation = assocs ary0
extraInformation = xExtension ++ yExtension ++ totalExtension
sumValues asscs = sum (map snd asscs)
xExtension = ...
yExtension = ...
totalExtension = [((maxX1, maxY1), sumValues priorInformation)]
((minX, minY), (maxX, maxY)) = bounds ary0
(maxX1, maxY1) = (succ maxX, succ maxY)
bounds1 = ((minX, minY), (maxX1, maxY1))
請注意,我們可以使用where
子句來定義諸如sumValues
將遍地出現新的功能。
然後我們可以通過priorInformation
來計算擴展名作爲列表解析。我們需要在舊的關聯上收集一種特定的總和---總結一個索引固定的所有值。
xExtension = [((maxX1, yix)
, sumValues (filter (\((_, j), _) -> j == yix) priorInformation)
)
| yix <- [minY .. maxY]
]
yExtension = [((xix, maxY1)
, sumValues (filter (\((i, _), _) -> i == xix) priorInformation)
)
| xix <- [minX .. maxX]
]
然後我們就完成了。效率不高,但所有的部分一起工作。
extend1A ary0 = array bounds1 (priorInformation ++ extraInformation) where
priorInformation = assocs ary0
extraInformation = xExtension ++ yExtension ++ totalExtension
xExtension = [((maxX1, yix)
, sumValues (filter (\((_, j), _) -> j == yix) priorInformation)
)
| yix <- [minY .. maxY]
]
yExtension = [((xix, maxY1)
, sumValues (filter (\((i, _), _) -> i == xix) priorInformation)
)
| xix <- [minX .. maxX]
]
totalExtension = [((maxX1, maxY1), sum xExtension)]
((minX, minY), (maxX, maxY)) = bounds ary0
(maxX1, maxY1) = (succ maxX, succ maxY)
bounds1 = ((minX, minY), (maxX1, maxY1))
大多數矩陣庫(據我所知)使用固定大小的數組,因此爲了延長一個,你就必須建立正確的尺寸之一,複製的內容將原始數組添加到新數組中。這基本上就是你在這裏做的,儘管這樣不會編譯,因爲你已經將'n'作爲數組和數組中的一個元素重用,所以這不會進行檢查或者進行任何數學意義上的檢查。 – bheklilr
謝謝。如果使用 n =數組((a,b),(c,d),(m,m)) 或者什麼? – haskellnoob
您仍然必須定義「m」是什麼。 Haskell無法自動找出你在這些位置需要的東西。你將不得不對齊類型簽名,你當前傳入的是一個類型爲'((Int,Int),(Int,Int))'的值,它不是'Array(Int, Int)Int'或'Int'。 – bheklilr