对不起,我说英语不好。
让我们看下面的代码。
main = getChar
首先,将评估main,它的值是“getChar”,但编译器不知道“getChar”值,因此编译器将评估“getChar”以计算“getChar”值,因此,getChar将被执行
实际上当我测试上面的代码时。 “getChar被执行。
让我们看看下面的代码。
main = return (getChar, getChar)
首先,主要评估,它的值是return(undefined,undefined) - > IO(未定义,未定义),因此前置将评估IO(未定义,未定义)以打印该值。所以将对两个getChar中的一个进行评估。
但是,当我测试上面的代码时,没有评估两个getChar。我不明白为什么两个getChar都没有被评估。
答案 0 :(得分:4)
您必须实际执行monadic操作,然后返回执行结果。
func = do
a <- getChar
b <- getChar
return (a,b)
您目前正在做的事情就像C声明:
void main(char &a, char &b)
{
a = getchar;
b = getchar;
}
与你真正想要的相反:
void main(char &a, char &b)
{
a = getchar();
b = getchar();
}
答案 1 :(得分:0)
“我想知道为什么两个getChar都没有被评估”
首先,用英语,如逻辑或数学或haskell,(不是(不是p))== p,因此你的问题是:
我想知道为什么要对这两个getChars进行评估。
令人困惑,因为我打赌他们都不会被评估。
您的main函数计算IO a的值,然后将评估类型为a的IO内的值。在您的情况下,a是(IO Char,IO Char)。因为Haskell是一种非严格的语言,所以评估元组只意味着构造元组。这不包括对元组组件的评估。例如:
fst (42, 7 `quot` 0 :: Int)
不会因为零错误而中止。 因此我们有:
(getChar, getChar)
是一个包含2个未评估值的元组。 但即使评估了这些值,我们也有2个IO Char类型的值。这样的值可以看作是在IO monad中执行时返回Char的行为。
因此,不仅没有评估你的元组组件,它们也不会在IO monad中执行。
要实现这一点,您可以将带有两个动作的元组传递给另一个动作:
executeBoth (a,b) = do
ra <- a
rb <- b
return (ra, rb)
现在,去检查一下executeBoth的类型,你可能会看到这一点。