2

我很抱歉我英语不好。

让我们看看下面的代码。

main = getChar

首先,main会被求值,它的值是“getChar”,但是编译器不知道“getChar”的值,所以编译器会求值“getChar”来计算“getChar”的值,这样,getChar就会被执行。

实际上,当我测试上面的代码时。“getChar 被执行。

让我们看看下面的代码。

main = return (getChar, getChar)

首先,main 求值,它的值是 return (undefined, undefined) -> IO (undefined, undefined),所以 prelude 会求值 IO (undefined, undefined) 来打印值。因此将评估两个 getChar 之一。

但是,当我测试上面的代码时,两个 getChar 都没有被评估。我不明白为什么没有两个 getChar 被评估。

4

2 回答 2

4

您必须实际执行您的一元操作,然后返回其执行结果。

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();
}
于 2012-05-13T00:41:41.947 回答
0

“我想知道为什么两个 getChar 都没有被评估”

首先,用英语,如逻辑或数学或haskell,(不是(不是p))== p,因此你的问题是:

我想知道为什么这两个 getChars 都被评估。

令人困惑,因为我敢打赌它们都没有被评估。

您的 main 函数计算 IO a 的值,然后将评估 IO 中类型为 a 的值。在您的情况下, 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 的类型,你可能会明白这一点。

于 2012-05-13T08:22:34.817 回答