模式匹配仅具有一个构造函数的类型

dsp*_*pyz 2 constructor haskell types pattern-matching lazy-evaluation

如果我对一个类型只有一个构造函数的表达式进行模式匹配,那还是会强制运行时将表达式计算为WHNF吗?


我做了一个似乎表明它没有评估的实验:

Prelude> data Test = Test Int Int
Prelude> let errorpr () = error "Fail"
Prelude> let makeTest f = let (x,y) = f () in Test x y
Prelude> let x = makeTest errorpr
Prelude> let Test z1 z2 = x
Prelude> :sprint z1
z1 = _
Prelude> :sprint z2
z2 = _
Prelude> :sprint x
x = _
Run Code Online (Sandbox Code Playgroud)

我本来希望得到一个错误或:sprint x得到

x = Test _ _
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.


显然我不明白"让"是如何运作的.请参阅以下答案

chi*_*chi 6

Prelude> let x = makeTest errorpr
Prelude> let Test z1 z2 = x
Run Code Online (Sandbox Code Playgroud)

最后一行不会强制评估任何内容:其中的模式let是(隐式)惰性模式(也称为无可辩驳的模式).试试吧

Prelude> let x = makeTest errorpr
Prelude> case x of Test z1 z2 -> "hello!"
Prelude> :sprint x
Run Code Online (Sandbox Code Playgroud)

你应该观察类似的事情Test _ _,因为模式case不是懒惰的.通过比较,

Prelude> let x = makeTest errorpr
Prelude> case x of ~(Test z1 z2) -> "hello!"   -- lazy pattern!
Prelude> :sprint x
Run Code Online (Sandbox Code Playgroud)

应该打印_,就像使用时一样let.

以上适用于data类型.相反,newtypes不提升内部类型,而是直接使用相同的表示.也就是说,newtype值构造和模式匹配在运行时是无操作:它们在类型检查后大致被编译器擦除.