Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching internals with a partially applied function

Imagine such a function:

bar :: Foo -> A -> B -> C -> IO ()

That function performs some IO stuff using a Foo and other values. The Foo value has to be passed to bar, and can be retrieved from IO via this:

foo :: X -> IO Foo

Now, A, B, C and X are all plain pure values. I’d rather like such a bar function:

bar :: X -> A -> B -> C -> IO ()

And Foo would be generated in the bar function using the X value. If I do that :

let f = bar myX

f :: A -> B -> C -> IO (). If I call that function several times, the X value remains the same because of partial application, but since it’s an IO effect, it will be generated each time. Is there a native, built-in-ghc way to perform some kind of caching so that the Foo value is generated once – for the generated closure? I guess it’s all boxing-related, but I never figured out how to do that without using dirty IORef, expanding the parameters of bar, which is ugly.

like image 348
phaazon Avatar asked Sep 04 '14 09:09

phaazon


People also ask

What is partial caching?

With partial file caching, the cache can fetch only the blocks that are read and not the entire file, thereby utilizing network and local disk space more efficiently. This is useful when an application does not need to read the whole file.


1 Answers

What you are literally asking would break referential transparency, a big "no" in Haskell. So that leaves me with the question, should I show you the unsafeLaunchMissiles kind of method that does (sometimes, if you are lucky and optimizations don't break it) what you literally ask but is highly discouraged, or should I show the clean way that changes the types just a little? Let me try the latter.

If you make your bar have the following type instead:

bar :: X -> IO (A -> B -> C -> IO ())

Then you can use, in a do block:

f <- bar myX

Alternatively, if you think that misses the point of redefining bar to take an X, then instead keep your first type for bar and do

f <- bar =<< foo myX
like image 193
Ørjan Johansen Avatar answered Sep 30 '22 02:09

Ørjan Johansen