【问题标题】:evaluate "main = return (getChar, getChar)"评估“main = return (getChar, getChar)”
【发布时间】:2012-05-13 00:28:59
【问题描述】:

对不起,我英语不好。

让我们看看下面的代码。

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 被评估。

【问题讨论】:

  • 顺便问一下,你从哪里得到 main 的结果应该打印出来的信息?事实并非如此。无论如何它都会被丢弃。
  • return X 不执行X 的效果。例如,main = return getChar 什么都不做。
  • 这里的任何人都可以提供该代码的应用样式版本来满足 OP 的要求吗?
  • @missingno: (,) <$> getChar <*> getChar

标签: haskell


【解决方案1】:

你必须实际执行你的一元动作然后返回它们的执行结果。

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();
}

【讨论】:

  • 谢谢你,托马斯。我知道我应该使用“do notation”顺序执行一元值。
  • 在那种情况下,我不明白你的问题是什么。如果您可以提供您想要的类型签名或行为以及您正在观察的内容,那将有所帮助。
  • 我想知道为什么两个 getChar 都没有被评估。
  • 好的,托马斯,对不起我的英语不好。在“main = getChar”中,getChar 被求值并执行。为什么?我认为“>>=”运算符用于“指定评估顺序 - 不用于执行”
  • @user1286894:你给main的是一个IO操作的描述。如果你写main = getChar,你告诉main 得到一个字符。如果你写return (getChar, getChar)会发生什么? return 可以被认为是一个不做任何事情并产生你指定的值的动作。问题来了:你说“什么都不做,把(getChar, getChar)还给我”,然后被忽略(main 的类型为IO ())。 &gt;&gt;= 用于组合两个动作一起,它可能意味着“一旦你执行第一个动作,获取它的结果并将其传递给第二个动作”。
【解决方案2】:

“我想知道为什么两个 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 的类型,你可能会明白这一点。

【讨论】:

  • 非常感谢。对不起,我错了。我修改了那个。这意味着“没有一个被评估”。
  • 阅读您的答案,所以现在我知道不会评估“main = (undefined, undefined)”。
  • 但是,我有一个问题。当haskell编译“main = getChar”时,我认为haskell将其评估为“main = undefined”,因此不会评估“getChar”。但是当我测试代码时,它被评估了。你能解释一下吗?
  • @user1286894 - main 的 (IO a) 结果将被评估执行。写return(getChar,getChar)的时候,结果就是IO(IO Char,IO Char)。执行外部 IO 操作并生成一个元组。元组的组件既不求值也不执行。
  • 非常感谢。我能理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-04
  • 2011-10-30
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多