I suppose what you're asking is, how to memoise a function. Memoisation means when a (possibly expensive) function has once been evaluated with some arguments x,y,z
and is at some later point evaluated with the exact same arguments again, the processor won't actually need to do all the computation again but just look up the result in some sort of table.
There are simple libraries for doing that. With MemoTrie
:
import Data.MemoTrie
f :: Int -> Int
f x = ... -- some expensive computation
fm :: Int -> Int
fm = memo f
Now if you call f 0
twice in a row, it will twice spend a long to to finish. OTOH, fm 0
will only take long the first time, the second time it'll give the result almost immediately.
If you know you only want to use f
memoised, you can also define it this way right away:
f :: Int -> Int
f = memo $ \x -> ...
Int -> Int
is just an example signature. The result of such a function can have any type you desire, and the arguments can also be pretty much any “discrete” type (any integral number, tuples, strings...).
MemoTrie
, like most such libraries, will only store the results in RAM. So when your program exists and you start it completely new, the memoised results will be gone and need to be computed anew, after all. Storing results persistently is more involved. I'm not aware of any library that does this in an automatic fashion. What's a bit problematic is that the state of which arguments have already been tried is not really part of the Haskell semantics.
I have recently dabbled with a project that does something very related, though.
https://github.com/leftaroundabout/lazy-hash