Partially used feature caching

Imagine a function like this:

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

This function does some IO stuff using Foo and other values. The value of Foo must be passed to bar and can be obtained from IO using this:

 foo :: X -> IO Foo 

Now A , B , C and X are all simple pure values. Id rather looks like a bar function like this:

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

And Foo will be generated in the bar function using the value of X If I do this:

 let f = bar myX 

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

+5
source share
1 answer

What you literally ask for will break link transparency, the big no in Haskell. Thus, this leaves me with the question of whether I should show you the unsafeLaunchMissiles method, which does (sometimes if you are lucky and the optimizations do not violate it) that you are literally asking, but very discouraged, or should I show a clean way, which changes types a little? Let me try the last one.

If you make your bar , instead:

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

Then you can use in the do block:

 f <- bar myX 

Alternatively, if you think you missed the bar redefinition point to take X , instead save your first type for bar and do

 f <- bar =<< foo myX 
+12
source

Source: https://habr.com/ru/post/1201799/


All Articles