Haskell罕见的模式匹配

Dam*_*ero 7 haskell pattern-matching

我的一位好朋友曾向我展示过这种罕见的haskell模式匹配行为

s@"Hello" = s 
Run Code Online (Sandbox Code Playgroud)

结果是:

>s
>"
Run Code Online (Sandbox Code Playgroud)

它开始打印字符串,但永远不会结束,是什么?

lef*_*out 10

@"Hello"这里是无关紧要的,它的作用是固定的类型String.你得到了同样的行为

s :: String
s = s
Run Code Online (Sandbox Code Playgroud)

这在语义上等同于

s' :: String
s' = undefined
Run Code Online (Sandbox Code Playgroud)

给出了结果

Prelude> s'
"*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)

我所说的"语义等价"是两个s并且s'都是底值的例子,即来自"任何类型包含的错误值的sin bin的值,由于非严格性".一旦你达到最低价值,纯粹的Haskell语言基本上是无能为力的,并且已经屈服于未定义的 "不纯行为",就像让你永远等待或抛出异常一样.

然而,再次感谢非严格性,这不一定需要发生.打印值时,首先发生的是,Show调用实例并要求生成一个字符串.Haskell字符串是一个惰性列表.和show任何字符串开头",因此即使字符串本身是完全不确定的,show会管理,以产生一个字符.

我们可以观察到更多的庇护

Prelude> head $ show s
'"'
Run Code Online (Sandbox Code Playgroud)


jbe*_*man 8

lets和顶级表达式中,左侧的所有内容都在=右侧的范围内.所以你创建了一个循环的"底部"值.

请注意,这行为方式相同:

Prelude> let s = (s::String)
Prelude> s
"
Run Code Online (Sandbox Code Playgroud)

那是因为(简化)printon String被定义为等同于:

printString chars = putChar '"' >> mapM_ putChar chars
Run Code Online (Sandbox Code Playgroud)

因为chars是一个循环mapM_ putChar chars似乎挂起.