为什么haskell代码没有终止 import Control.Monad.State.Lazy 类型队列a=[a] 推送::a->状态(队列a)() push x=state(\xs->((),xs++[x])) 状态(队列a)a pop=状态(\(x:xs)->(x,xs)) queueManip::状态(队列Int)Int 队列管理= 做 地图推送[1..] a
注意,为什么haskell代码没有终止 import Control.Monad.State.Lazy 类型队列a=[a] 推送::a->状态(队列a)() push x=state(\xs->((),xs++[x])) 状态(队列a)a pop=状态(\(x:xs)->(x,xs)) queueManip::状态(队列Int)Int 队列管理= 做 地图推送[1..] a,haskell,lazy-evaluation,state-monad,Haskell,Lazy Evaluation,State Monad,注意,domapm_uuupush[1..3];某些内容与以下内容相同: import Control.Monad.State.Lazy type Queue a = [a] push :: a -> State (Queue a) () push x = state (\xs -> ((),xs++[x])) pop :: State (Queue a) a pop = state (\(x:xs) -> (x,xs)) queueManip :: State (Qu
domapm_uuupush[1..3];某些内容与以下内容相同:
import Control.Monad.State.Lazy
type Queue a = [a]
push :: a -> State (Queue a) ()
push x = state (\xs -> ((),xs++[x]))
pop :: State (Queue a) a
pop = state (\(x:xs) -> (x,xs))
queueManip :: State (Queue Int) Int
queueManip =
do
mapM_ push [1..]
a <- pop
return a
main :: IO()
main = do
let (a,_) = runState queueManip []
print a
这应该可以解释为什么
do push 1; push 2; push 3; something
永远不要抽出时间来执行某件事
如果您查看状态单子的定义:
do mapM_ push [1..]; something
您可以看到m>=g
的值始终取决于g
。与Maybe
monad的定义相比:
type State s a = s -> (a, s)
instance Monad (State s) where
return a = \s -> (a,s)
m >>= g = wpAB
where
wpAB = \s1 -> let (v2, s2) = m s1
(v3, s3) = g v2 s2
in (v3, s3)
-- (newtypes and such have been removed to declutter the code)
其中,m>>=g
可以独立于g
,这解释了可能
单子可以短路do链。如果我是邪恶的,使用
instance Monad Maybe where
return x = Just x
(>>=) m g = case m of
Nothing -> Nothing
Just x -> g x
然后mapmpush'[1..]
应清楚地将状态呈现为[1052602983,1052602984..]
。pop
产生1
是错误的。但是mapM
不可能知道这一点,除非先计算出10亿个其他数字。实际上,将它们推到状态在这里是不相关的,push
可能完全是懒惰的,这也没关系:mapM
在提交一元程序流之前,至少要给它一个检查任何给定数字的机会。虽然不完全相同,但你看了吗?我认为这可能是一个有效的论点,但是你仍然需要证明,一个无限的do
链不能像Haskell中的许多其他东西一样被懒散地跳过。是的,有一些单子,其中一个do无限链不必被完全计算-例如,Maybe单子。那么,为什么参数对状态
有效呢,有没有办法通过其他monad实现队列?所需的惰性是否可以通过其他monad实现?只需从queueManip
中删除mapM\uupush[1..]
并使用runState queueManip[1..]
运行计算即可。
push' :: Int -> State (Queue Int) ()
push' 1052602983 = state $ \_ -> ((), []) -- "Muarhar!"
push' x = state $ \xs -> ((),xs++[x])