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)
在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似乎挂起.