yon*_*ong 13 haskell lazy-evaluation state-monad
严格的状态monad定义使用:
m >>= k = State $ \s ->
case runState m s of
(a, s') -> runState (k a) s'
Run Code Online (Sandbox Code Playgroud)
但这仍然会泄漏记忆,因为a
并且没有s'
得到评估.例如,我们可能有一个函数f
将大对象作为输入并快速返回(a, s')
,但只要a
没有评估,输入f
就不能被GC.
一个可能的解决方案是f
返回seq a (a, s')
,但如果我们使用类似的东西MonadRandom
,这并不总是可能的,并且状态被封装起来f
.是否有这样定义的版本:
m >>= k = State $ \s ->
case runState m s of
(!a, !s') -> runState (k a) s'
Run Code Online (Sandbox Code Playgroud)
这已存在于任何地方的图书馆吗?
根据monad身份法,
return a >>= const b = const b a = b
Run Code Online (Sandbox Code Playgroud)
特别是,
return undefined >>= const b = b
Run Code Online (Sandbox Code Playgroud)
如果>>=
操作对结果值严格,那将破坏这个定律,所以你不应该这样做.
假设您这样做:
m >>= k = State $ \s ->
case runState m s of
(a, !s') -> runState (k a) s'
Run Code Online (Sandbox Code Playgroud)
现在我们面临另一个身份法:
m >>= return = m
Run Code Online (Sandbox Code Playgroud)
例如,
return a >>= return = return a
Run Code Online (Sandbox Code Playgroud)
所以如果return a >>= return
是严格的状态,那么我们也必须return a
在国家严格!所以我们也需要重新定义return
:
return a = State $ \ !s -> (a, s)
Run Code Online (Sandbox Code Playgroud)
请注意,您实际上不需要执行任何操作; 如果你愿意,你可以使用通常的严格状态monad,并写出类似的东西
!_ <- get
Run Code Online (Sandbox Code Playgroud)
在你想强迫国家的地方.你甚至可以写一个动作来做到这一点:
forceState :: Monad m => StateT s m ()
forceState = get >>= \ !_ -> return ()
Run Code Online (Sandbox Code Playgroud)
即使这个定义对我来说也有点奇怪; 我希望lambda强迫国家,而不是case
.我不确定如果不这样做会导致某种破损,但如果确实如此,我不会感到惊讶.
归档时间: |
|
查看次数: |
564 次 |
最近记录: |