Wikibooks(http://en.wikibooks.org/wiki/Haskell/Simple_input_and_output)
的一个例子doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else putStrLn "You Win!"
Wikibooks说&#39; doGuessing num&#39;在外部&#34;然后&#34;中有类型IO()分支。
do putStrLn "Too low!"
doGuessing num
我不明白为什么要这么做#num;&#39;有类型IO(),只是猜测这是因为:
1)the last "else" brance (putStrLn "You Win!") has type IO ().
2)in Haskell, "then" branch and the "else" branch have the same type.
3)the final action (putStrLn "You Win!") defines the type of the whole do block.
所以&#39; doGuessing num&#39;有类型IO()。
我不确定我的理解是对的。行动对我来说是新的,如果我错了,请纠正我。
答案 0 :(得分:4)
基本上,所有这一切。在这个例子中,有很多方法可以让Haskell推断出类型。
(除了您所说的内容:do
块中的所有操作都必须在同一个monad中;第一个putStrLn "Enter your guess: "
已经为您提供doGuessing
} IO
monad(即IO a
代表某些未知的a
。()
产生的putStrLn
与此无关。)
guess <- getLine
也是如此,这也是IO
行动。)
关于像Haskell这样的Hindley-Milner类型系统的好处在于,没有一条“路线”可以了解类型信息如何通过代码传递。并不是类型信息以某种方式附加到值,如动态语言。 (C ++或Java使用的类型推断类型基本上是该动态类型流的“预模拟”。) 相反,编译器收集它可以在任何地方找到的所有信息,并将其组合以推断整个表达式的类型。正如musically_ut已经在评论中提到的那样,这是通过type unification完成的。