问题 ViewPatterns和Haskell中的多个调用


我看了这个:

http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns

我喜欢这个想法,想要使用扩展名。然而,我想确定一件事:是否对单个匹配评估了一次视图函数。

所以我们说:

{-# LANGUAGE ViewPatterns #-}
...

f (view -> Nothing) = ...
f (view -> Just x) = ...

view :: a -> Maybe b

现在让我说我调用 f a。是 view 为给定的参数调用两次或只调用一次 a

编辑

我试图找出是否是这种情况并写下以下内容:

{-# LANGUAGE ViewPatterns #-}

import System.IO.Unsafe

blah (ble -> Nothing) = 123
blah (ble -> Just x) = x

ble x = unsafePerformIO $ do
    putStrLn $ "Inside ble: " ++ show x
    return x

main :: IO ()
main = do
    putStrLn $ "Main: " ++ show (blah $ Just 234)

使用GHC输出:

Inside ble: Just 234
Inside ble: Just 234
Main: 234

使用GHC输出(带优化)

Inside ble: Just 234
Main: 234

使用GHCi输出:

Main: Inside ble: Just 234
Inside ble: Just 234
234

6955
2018-01-20 20:12


起源

GHC有一个特殊的hack来避免重新计算相同的视图表达式。 - augustss


答案:


就一次:

效率:当应用相同的视图功能时 函数定义或案例表达的多个分支(例如, 在 size 以上),GHC试图收集这些 将应用程序转换为单个嵌套的case表达式,以便进行视图 功能仅应用一次。 GHC中的模式编译遵循 矩阵算法在第4章中描述 该 功能编程语言的实现。当。。。的时候 矩阵的第一列的顶行是具有的所有视图模式 “相同”表达式,将这些模式转换为单个嵌套 案件。这包括例如排列的相邻视图模式 在一个元组中,如在

f((view  - > A,p1),p2)= e1
f((view  - > B,p3),p4)= e2

两个视图模式表达式的当前概念是“ 同样“非常有限:它甚至没有完全的句法平等。 但是,它确实包含变量,文字,应用程序和元组; 例如,两个实例 view ("hi", "there") 将会 集。但是,目前的实施情况并不比较 alpha等价,所以两个实例 (x, view x -> y) 不会合并。

- GHC手册

至于你的代码片段,问题在于你没有编译优化;既 ghc -O 和 ghc -O2,该行只打印一次。在使用GHC时遇到与性能相关的问题时,首先要检查的是:)

(顺便一提, Debug.Trace 让您检查这些类型的东西,而无需编写手册 unsafePerformIO 黑客。)


13
2018-01-20 20:15



由于performUnsafeIO,GHC是否有可能插入额外的备用评估?别担心,我用它来测试这个功能。 - julkiewicz
我添加了一个具体的代码示例。 - julkiewicz
@julkiewicz:我已经更新了我的答案:) - ehird
是的,那我还是个新手。非常感谢! - julkiewicz
出于某种原因,我觉得我喜欢使用 Debug.Trace 很好,但是 unsafePerformIO 尽管如此,通常是可怕的 Debug.Trace 只是使用 unsafePerformIO 在引擎盖下。 - Dan Burton