想象这样一个函数:
bar :: Foo -> A -> B -> C -> IO ()
该函数使用Foo
和其他值来执行一些IO
内容。Foo
值必须传递给bar
,并且可以通过以下方式从IO
检索:
foo :: X -> IO Foo
现在,A
、B
、C
和X
都是纯值。我更喜欢这样一个bar
函数:
bar :: X -> A -> B -> C -> IO ()
并且Foo
将使用X
值在bar
函数中生成。如果我这样做:
let f = bar myX
f :: A -> B -> C -> IO ()
。如果我多次调用该函数,由于部分应用,X
值保持不变,但由于它是IO
效果,每次都会生成。是否有原生,内置于ghc的方式来执行某种缓存,以便为生成的闭包生成一次Foo
值?我想这一切都与拳击有关,但我从未想过如何在不使用脏IORef
的情况下做到这一点,扩展bar
的参数,这很难看。
您实际要求的是破坏引用透明度,这在Haskell中是一个很大的"否"。这就给我留下了一个问题,我是应该向你展示unsafeLaunchMissiles
类型的方法,它能做到(有时,如果你幸运的话,优化不会破坏它)你真正要求的,但却非常不鼓励,还是应该展示稍微改变类型的干净方法?让我试试后者。
如果您使bar
具有以下类型:
bar :: X -> IO (A -> B -> C -> IO ())
然后,您可以在do
块中使用:
f <- bar myX
或者,如果您认为这错过了将bar
重新定义为X
的要点,那么请保留bar
的第一个类型,并执行
f <- bar =<< foo myX