作者Favonia (小西风最乖了*^^*)
看板PLT
标题Re: [问题] Lazy Evaluation?
时间Tue Nov 15 01:14:36 2011
※ 引述《slyfox (klanloss)》之铭言:
: 失败版:
: sequenceWhile :: Monad m => (a -> Bool) -> [m a] -> m [a]
: sequenceWhile f ms = sequence ms >>= return . takeWhile f
: getCharUntil' c = sequenceWhile (/=c) $ repeat getChar
: 失败版会一直读不停
: Lazy evaluation 很耐死的,一定是有什麽误会…
: → slyfox:但在此例 sequence 被 >>= 规定要"算到底"吧? 11/14 15:10
(不好意思违反版规建议,请帮我把推文删掉 orz)
>>= 需要判断左边有没有会导致错误的指令,而 sequence ms
要如何决定有没有会导致错误的指令?只能全部看过一次!可惜这
个串列怎麽看都看不完。
题外话是 sequence 为了检查会不会产生错误时不需要把每个
指令的结果都「展开到最後」,也就是「算到底」。实际上除非用
deepseq 之类的东西恶搞否则很难算到底...
=== 真相版 ===
上面的理解有个作弊的地方,就是我假设 sequenceWhile 要
算到至少 Weak head normal form (WHNF). 实际上得从 main 开
始逆推才知道什麽是非算不可的...
Haskell 各个函数计算上的意义比较像是「如何拖人下水」
(下水 = 变身成 WHNF)或「如何变身」。理论上有人要拖
sequence ms 下水时,它可以先用 pattern matching 拖人下水,
然後再根据定义变身成 foldr. 可惜这样还不够(还不是 WHNF
所以还没掉到水里),所以变身成 foldr 後继续被拖。接着
foldr 可以再用 pattern matching 拖他的参数下水... 文章中
拖来拖去的关系恰好会尝试把串列中每个元素都拖下去,所以跑
不完。
凡是总要有起头,基本上一开始 main 就会直接被拖下水,
看看多少人会一起掉下去。喔,然後编译器会在尽量保留语意的
情况下
(理想上是完全保留语意,但是...)用比较有效率方法
实作这种拖人下水的机制;尤其 GHC 实作一堆奇怪的最佳化,
最後真正跑的程式码可能跟你在 Prelude.hs 翻到的相去甚远...
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.112.30.39
※ 编辑: Favonia 来自: 140.112.30.39 (11/15 01:15)
※ 编辑: Favonia 来自: 140.112.30.39 (11/15 01:16)
※ 编辑: Favonia 来自: 140.112.30.39 (11/15 01:17)
※ 编辑: Favonia 来自: 140.112.30.39 (11/15 01:18)
1F:推 godfat:谢谢 :) 是否修改推文则由原作者决定吧 11/15 11:01
2F:推 slyfox:了解 感谢~ 鱼好吃 钓竿有好推荐吗? 11/15 12:06
※ 编辑: Favonia 来自: 140.112.30.39 (11/16 01:12)