Haskell 中的 ViewPatterns 和多次调用

发布于 2024-12-28 06:52:46 字数 1117 浏览 4 评论 0原文

我读到了这个:

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

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

假设我们有:

{-# LANGUAGE ViewPatterns #-}
...

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

view :: a -> Maybe b

现在假设我调用 f a。对于给定的参数aview 是调用了两次还是只调用了一次?

编辑

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

{-# 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)

Output using GHC:

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

Output using GHC (with optimization)

Inside ble: Just 234
Main: 234

Output using GHCi:

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

I read this:

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

I like the idea, want to use the extension. I however would like to make sure as to one thing: whether the view function is evaluated once for a single matching.

So let's say we have:

{-# LANGUAGE ViewPatterns #-}
...

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

view :: a -> Maybe b

Now let's say I invoke f a. Is view invoked twice or just once for the given argument a?

EDIT:

I tried to find out whether this is the case and wrote the following:

{-# 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)

Output using GHC:

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

Output using GHC (with optimization)

Inside ble: Just 234
Main: 234

Output using GHCi:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最偏执的依靠 2025-01-04 06:52:46

就一次:

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

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


当两个视图模式表达式是“ 相同”是非常有限的:它甚至不是完全的语法相等。 然而,它确实包括变量、文字、应用程序和元组; 例如,view ("hi", "there") 的两个实例将是 集。然而,当前的实现并不能与 alpha 等价,因此 (x, view x -> y) 的两个实例不会合并。

GHC 手册

作为对于您的代码片段,问题在于您没有进行优化编译;使用 ghc -O 和 ghc -O2 时,该行仅打印一次。当您在使用 GHC 时遇到与性能相关的问题时,这始终是首先要检查的事情:)

(顺便说一下,Debug.Trace 让您可以检查此类内容,而无需编写手动 unsafePerformIO hack。)

Just once:

Efficiency: When the same view function is applied in
multiple branches of a function definition or a case expression (e.g.,
in size above), GHC makes an attempt to collect these
applications into a single nested case expression, so that the view
function is only applied once. Pattern compilation in GHC follows the
matrix algorithm described in Chapter 4 of The
Implementation of Functional Programming Languages
. When the
top rows of the first column of a matrix are all view patterns with the
"same" expression, these patterns are transformed into a single nested
case. This includes, for example, adjacent view patterns that line up
in a tuple, as in

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

The current notion of when two view pattern expressions are "the
same" is very restricted: it is not even full syntactic equality.
However, it does include variables, literals, applications, and tuples;
e.g., two instances of view ("hi", "there") will be
collected. However, the current implementation does not compare up to
alpha-equivalence, so two instances of (x, view x -> y) will not be coalesced.

The GHC manual

As for your snippet, the problem is that you're not compiling with optimisation; with both ghc -O and ghc -O2, the line is only printed once. That's always the first thing to check when you have performance-related problems when using GHC :)

(By the way, Debug.Trace lets you check these kinds of things without having to write manual unsafePerformIO hacks.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文