2010-10-17 159 views
5

爲了緩存的目的,我想創建一個數組,它將函數的輸入值映射爲輸出值。我知道,我的功能將在這一特定範圍內只用,我想是這樣的:如何從一個函數創建一個Haskell數組

MyType = ... deriving (Ix) 

myFunction :: MyType -> foo 

myCache = createArrayFromFunction (start,end) myFunction 

這是可能的,或者我只是覺得「不實用」,並有另一種解決方案。我需要數組,因爲我需要O(1)訪問成員並從頭開始知道長度。

+0

這是完全有效的(我經常這樣做)。事實上,你可以定義一個'createArrayFromFunction'函數,這樣你的代碼就可以工作。 – 2010-10-17 14:13:34

回答

6

如果你只是想創建一個高速緩存,那麼你可以只用listArraymap,只要你把所有的索引列表:

myCache :: Array MyType Foo 
myCache = listArray (start,end) . map myFunction $ range (start,end) 

我認爲MyTypeEnum實例這裏;如果沒有,您需要一些其他方式來生成有效輸入列表,這取決於您的類型。正如裏德巴頓指出的那樣,這就是range

另一種選擇,如果你想呈現給用戶的功能,將

myInternalFunc :: MyType -> Foo 
myInternalFunc mt = (complex calculation) (using mt) 

myFuncCache :: Array MyType Foo 
myFuncCache = listArray (start,end) . map myFunction $ range (start,end) 

myFunction :: MyType -> Foo 
myFunction = (myFuncCache !) 

然後,你就不會從你的模塊輸出myInternalFunc;你可能不會出口myFuncCache,但我可以想象需要它。如果您不在模塊中,則可以將myInternalFunc置於let - 或where - myFuncCache之內。一旦你這樣做,myFunction mt只是做一個緩存查找,所以是O(1)。

+1

使用'range(start,end)'(http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-Ix.html#v:range),而不是' [start..end]'。 – 2010-10-17 14:11:43

+0

@Reid:謝謝!我不使用陣列太多。 – 2010-10-17 14:56:28

+0

原因是我知道我的函數只有500個特定的輸入值,但計算結果需要很長時間。謝謝。 – fuz 2010-10-18 06:27:26

3

如果您正在查看陣列,那麼也請考慮Vector。除了融合和強大的拼接功能,值得注意的一個重要區別是矢量都是Int索引。使用這個庫你的世代功能是:

generate :: Int -> (Int -> a) -> Vector a 
+0

問題是:我想要一些不是Int索引的東西。 – fuz 2010-10-20 04:10:20

+0

如果你有一個Enum,那麼你正在使用IS'Int'以一種說話的方式進行索引。事實上,如果你的類型是'Ix'的一個實例,那麼爲你的索引需要製作一個Vector的wrapper應該不難。 – 2010-10-20 04:16:45

相關問題