5

For caching purposes, I want to create an array, which maps input values of the function to output values. I know, that my function will be used only in this specific range, I think about something like this:

MyType = ... deriving (Ix)

myFunction :: MyType -> foo

myCache = createArrayFromFunction (start,end) myFunction

Is this possible or do I just think "not functional" and there is another solution. I need arrays, because I need O(1) access to the members and know the length from the beginning.

1
  • This is entirely functional (and I do it quite often). In fact, you can define a createArrayFromFunction function so that your code will work. Commented Oct 17, 2010 at 14:13

2 Answers 2

6

If you just want to create a cache, then you can just use listArray and map, as long as you have a list of all your indices:

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

I assumed that MyType has an Enum instance here; if it doesn't, you'll need some other way to generate a list of valid inputs, which depends on your type. As Reid Barton pointed out, this is what range is for.

Another option, if you want to present a function to the user, would be

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 !)

Then you wouldn't export myInternalFunc from your module; you probably wouldn't export myFuncCache either, but I could imagine needing it. If you aren't in a module, you could put myInternalFunc in a let- or where-block within myFuncCache. Once you do this, myFunction mt just does a cache lookup, and so is O(1).

Sign up to request clarification or add additional context in comments.

4 Comments

Use range (start, end) (haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/…), not [start..end].
@Reid: Thanks! I don't use Arrays much.
The reason is just, that I know, that my function takes only some 500 specific input values, but it takes a long time to calculate the results. Thx.
Can anyone tell me if this array cache is calculated lazily?
3

If you're looking at arrays then also consider Vector. Aside from fusion and powerful splicing function, an important difference worth noting is Vectors are all Int indexed. Using this library your generation function is:

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

2 Comments

The problem is: I want something which isn't Int indexed.
If you have an Enum then what you are using IS Int indexed in a manner of speaking. Indeed, if your type is an instance of Ix it shouldn't be hard to make a wrapper around Vector for your indexing needs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.