Dav*_*ric 2 haskell lazy-evaluation strictness
我有点困惑如何重写严格评估列表理解以使用seq而不是bang模式:
zipWith' f l1 l2 = [ f e1 e2 | (!e1, !e2) <- zip l1 l2 ]
Run Code Online (Sandbox Code Playgroud)
任何的想法 ?
我试过了
zipWith' f l1 l2 = [ e1 `seq` e2 `seq` f e1 e2 | (e1, e2) <- zip l1 l2 ]
Run Code Online (Sandbox Code Playgroud)
但不幸的是,这并未强制对WHNF进行评估.
您可以机械地将爆炸模式转换为seq
遵循GHC手册的调用:
这个:
zipWith' f l1 l2 = [ f e1 e2 | (!e1, !e2) <- zip l1 l2 ]
Run Code Online (Sandbox Code Playgroud)
变得懒得:
zipWith' f l1 l2 =
[ f e1 e2
| e <- zip l1 l2
, let t = case e of (x,y) -> x `seq` y `seq` (x,y)
, let e1 = fst t
, let e2 = snd t
]
Run Code Online (Sandbox Code Playgroud)
哪个更简洁地写成(太懒):
zipWith' f l1 l2 =
[ f e1 e2
| e <- zip l1 l2
, let (e1,e2) = case e of (x,y) -> x `seq` y `seq` (x,y)
]
Run Code Online (Sandbox Code Playgroud)
虽然我把它写成(错误,懒得)
zipWith' f l1 l2 = zipWith (\x y -> uncurry f (k x y)) l1 l2
where
k x y = x `seq` y `seq` (x, y)
Run Code Online (Sandbox Code Playgroud)
您还可以将严格提示移动到数据结构:
data P = P !Integer !Integer
zipWith' f l1 l2 = [ f e1 e2 | P e1 e2 <- zipWith P l1 l2 ]
Run Code Online (Sandbox Code Playgroud)
或者:
zipWith' f l1 l2 = [ f e1 e2 | (e1, e2) <- zipWith k l1 l2 ]
where
k x y = x `seq` y `seq` (x,y)
Run Code Online (Sandbox Code Playgroud)
您希望严格zipWith要做的基本事情是在强制使用cons单元时评估列表的元素.你的功能不会这样做.试一试
main = print $ length $ zipWith' undefined [1..10] [1..100]
Run Code Online (Sandbox Code Playgroud)
当您使用(+)使其工作时,这是严格性分析的侥幸.
你想要的功能是这样的:
zipW f (x:xs) (y:ys) = let z = f x y in seq z (z : zipW f xs ys)
zipW _ _ _ = []
Run Code Online (Sandbox Code Playgroud)
你不能将cons细胞的产生与价值的产生分开,因为前者应该强迫后者.
| 归档时间: |
|
| 查看次数: |
641 次 |
| 最近记录: |