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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With