鉴于:
?: let f = putStrLn "foo" in 42
42
Run Code Online (Sandbox Code Playgroud)
什么是f类型?为什么"foo"在显示结果之前没有打印42?
最后,为什么以下不起作用?
?: :t f
<interactive>:1:1: Not in scope: ‘f’
Run Code Online (Sandbox Code Playgroud)
Vai*_*gar 13
什么是
f类型?
正如您已经正确识别的那样,IO ()可以将其视为一个不会返回任何有用的IO操作(())
为什么在显示结果之前不会打印"foo"
42?
Haskell被懒惰地评估,但seq在这种情况下甚至还不够.如果表达式返回IO操作,则只会在REPL中执行IO操作.只有在返回时,才会在程序中执行IO操作main.但是,有办法解决这个限制.
最后,为什么以下不起作用?
Haskell let在表达式的范围内命名一个值,因此在评估表达式之后f超出范围.
chi*_*chi 10
let f = ...简单地定义f,并且不"运行"任何东西.它与命令式编程中的新函数的定义模糊地类似.
您的完整代码let f = putStrLn "foo" in 42可能会被松散地翻译成
{
function f() {
print("foo");
}
return 42;
}
Run Code Online (Sandbox Code Playgroud)
你不会指望上面打印任何东西,对吗?
相比之下,let f = putStrLn "foo" in do f; f; return 42类似于
{
function f() {
print("foo");
}
f();
f();
return 42;
}
Run Code Online (Sandbox Code Playgroud)
通信并不完美,但希望你能得到这个想法.
f将是类型IO ().
"foo"没有打印,因为f它没有"绑定"到现实世界.(我不能说这是一个友好的解释.如果这听起来很废话,你可能想参考一些教程来了解Monad和懒惰评估的想法).
let name = value in (scope)使值可用,但不在范围之外,因此:t不会在ghci的顶级范围内找到它.
let没有in使它可用:t(此代码仅在ghci中有效):
> let f = putStrLn "foo"
> :t f
f :: IO ()
Run Code Online (Sandbox Code Playgroud)