给定数据类型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
总是抛出其单个参数,这是否意味着它的参数永远不会被评估,甚至不会被评估为弱头范式?
答案 0 :(得分:4)
功能&#34; f&#34;正如你所说,永远不会评估它的论点。这与参数是否为&#34; Show&#34;。
的实例无关你也可以说
Prelude> let f2 _ = "Some value"
Prelude> f2 (Foo 5)
"Some value"
但真正的一点是,即使f2的参数未定义,也不会被评估,因此不会抛出异常
Prelude> f2 undefined
"Some value"
答案 1 :(得分:3)
不,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
>>> :set -XBangPatterns
>>> let h !_ = "bad"
>>> h undefined
"*** Exception: Prelude.undefined
或模式匹配:
>>> let k (Foo _) = "bad"
>>> k undefined
"*** Exception: Prelude.undefined
但您可以使用~
>>> let j ~(Foo _) = "bad"
>>> j undefined
"bad"
答案 2 :(得分:1)
Prelude> let f _ = error("bad!")
Haskell为lazy,_
param根本不予评估。
要记住的口号是“模式匹配驱动评估”。至 重申重点:
Expressions are only evaluated when pattern-matched …only as far as necessary for the match to proceed, and no farther!