想象一下这样一个功能:
bar :: Foo -> A -> B -> C -> IO ()
该函数使用IO
和其他值执行一些Foo
内容。 Foo
值必须传递给bar
,并且可以通过以下方式从IO
检索:
foo :: X -> IO Foo
现在,A
,B
,C
和X
都是纯粹的纯值。我更喜欢这样的bar
函数:
bar :: X -> A -> B -> C -> IO ()
使用Foo
值在bar
函数中生成X
。如果我这样做:
let f = bar myX
f :: A -> B -> C -> IO ()
。如果我多次调用该函数,X
值因部分应用而保持不变,但由于它是IO
效果,因此每次都会生成Foo
。是否存在 native , built-in-ghc 方式来执行某种缓存,以便为生成的闭包生成IORef
值一次?我想这与拳击有关,但我从来没有想过如何在不使用脏bar
的情况下做到这一点,扩展{{1}}的参数,这很难看。
答案 0 :(得分:12)
你真正要求的是打破参考透明度,一个大的" no"在哈斯克尔。所以这给我留下了一个问题,我是否应该向你展示unsafeLaunchMissiles
那种方法(有时候,如果你很幸运并且优化不会破坏它)你真正要求但却非常沮丧,或者我应该展示一下改变类型的干净方式吗?让我试试后者。
如果您使bar
改为使用以下类型:
bar :: X -> IO (A -> B -> C -> IO ())
然后您可以在do
块中使用
f <- bar myX
或者,如果您认为错过了重新定义bar
以获取X
的重点,那么请保留{em} 的第一个类型并执行< / p>
bar