`_` 函数参数的评估(或根本 none)?

Evaluation (or none at all) of `_` Function Argument?

给定数据类型,Foo:

Prelude> data Foo a = Foo a

没有实现Show,所以无法打印。

Prelude> Foo 5
<interactive>:13:1:
    No instance for (Show (Foo a0)) arising from a use of ‘print’

但是,给定一个总是抛出异常的函数:

Prelude> let f _ = error("bad!")

f可以套用。

Prelude> f (Foo 5)
*** Exception: bad!

由于 f 总是为其单个参数抛出异常,这是否意味着它的参数永远不会被评估,甚至不会对 Weak Head Normal Form 进行评估?

不,f 的参数未被评估。一个简单的测试方法是使用 undefined,一旦它被触摸就会抛出一个错误:

>>> undefined
*** Exception: Prelude.undefined

>>> let f _ = "bad"

>>> f undefined
"bad"

但您可以编写一个类似的函数,使用 seq:

评估其对 WHNF 的参数
>>> let g a = a `seq` "bad"
>>> g undefined
"*** Exception: Prelude.undefined

BangPatterns:

>>> :set -XBangPatterns 
>>> let h !_ = "bad"
>>> h undefined 
"*** Exception: Prelude.undefined

或模式匹配:

>>> let k (Foo _) = "bad"
>>> k undefined 
"*** Exception: Prelude.undefined

但您可以使用 ~:

来执行 lazy pattern match
>>> let j ~(Foo _) = "bad"
>>> j undefined 
"bad"
Prelude> let f _ = error("bad!")

Haskell 是 lazy_ 参数根本没有计算。

The slogan to remember is “pattern matching drives evaluation”. To reiterate the important points:

Expressions are only evaluated when pattern-matched

…only as far as necessary for the match to proceed, and no farther!

函数 "f" 从不计算它的参数,正如你所说的。这与参数是否是 "Show".

的实例无关

你也可以说

Prelude> let f2 _ = "Some value"

Prelude> f2 (Foo 5)
"Some value"

但真正的重点是,即使 f2 的参数未定义,它也不会被求值,因此不会抛出异常

Prelude> f2 undefined
"Some value"