在Haskell中,我可以这样做:
结果如下:
s@"Hello" = s
结果如下:
>s
>"
开始打印字符串但是从未结束,发生了什么事情?
s@"Hello" = s
>s
>"
开始打印字符串但是从未结束,发生了什么事情?
@"Hello"
在此无关紧要,它只是将类型固定为String
。您可以使用相同的方法:
s :: String
s = s
这与语义上等同于
s' :: String
s' = undefined
提供结果
Prelude> s'
"*** Exception: Prelude.undefined
“语义上等价”是指,s
和s'
都是“底部值”的示例,即任何类型都包含的“错误值集合”,因为类型是非严格的。一旦遇到底部值,纯Haskell语言基本上就无能为力了,只能让步于“未定义”,“不纯的行为”,比如让你永远等待或抛出异常。
然而,再次由于非严格性,这并不一定会发生。打印一个值时,首先发生的是调用Show
实例,并要求生成一个字符串。Haskell字符串是一个惰性列表。而任何字符串的show
都以"
开头,因此即使字符串本身是未定义的,show
也能够生成那一个字符。
我们可以更加安全地观察这个问题:
Prelude> head $ show s
'"'
Prelude> let s = (s::String)
Prelude> s
"
print
的定义相当于:printString chars = putChar '"' >> mapM_ putChar chars
chars
是一个循环,所以mapM_ putChar chars
看起来会挂起。let 1=2
。你能解释一下吗? - Eugene Sh.let x@1 = 2 in x
将失败,let !1 = 2 in ()
也将失败。但是对于let 1 = 2 in ()
,没有任何东西会强制Haskell实际执行所请求的模式匹配。 - Antal Spector-Zabusky