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).
createArrayFromFunctionfunction so that your code will work.