【问题标题】:Haskell IO monad and do notationHaskell IO monad 和 do 表示法
【发布时间】:2013-04-05 12:02:10
【问题描述】:

以下 Haskell 代码段无法编译,我不知道为什么。

runCompiler :: TC -> IO ()
runCompiler tc = let cp' = cp in 
    do 
        cp'
        return ()
    where
    cp = compileProg tc

我从 GHCi 收到以下错误:

    Couldn't match expected type `IO a0' with actual type `String'
    In a stmt of a 'do' block: cp'
    In the expression:
      do { cp';
           return () }
    In the expression:
      let cp' = cp
      in
        do { cp';
             return () }

任何想法如何使它编译。我不明白为什么它不接受 () 作为给定的最终值。

【问题讨论】:

  • compileProg 的类型签名是什么?
  • 为什么要将compileProg tc 绑定到cp'cp?为什么在同一个函数中同时使用letwhere?令人困惑。
  • 当我将其更改为下面的答案时,它会编译。现在我的问题是让它输出 compileProg 返回的字符串。

标签: haskell io monads


【解决方案1】:

当使用do 符号对两个语句进行排序时:

do
    action1
    action2

action1 >> action2相同

因为>> 的类型为Monad m => m a -> m b -> m b,所以action1action2 都应该是一元值。

您的compileProg 函数似乎具有TC -> String 类型,而编译器希望它是TC -> IO a 某些a,因为您在do 表示法中使用它。

您可以使用let

do 
    let _ = compileProg tc
    return ()

让它编译。

如果要输出返回的字符串,可以使用putStrLnprint

do
    putStrLn (compileProg tc)
    return ()

由于putStrLn 具有String -> IO () 类型,您可以删除return ()

do
    putStrLn (compileProg tc)

其实runCompiler可以简单写成

runCompiler :: TC -> IO ()
runCompiler = putStrLn . compileProg

【讨论】:

  • 我想要做的是在屏幕上显示 compileProg 的输出。 compileProg 的类型签名是 TC -> String.
  • @StuartPaton 那么你想要putStrLn (compileProc tc)
  • 澄清@lee 的回答:do 块中的每个语句都有IO a 的类型(或者它可以是let 绑定)。 cp' 的类型为 String,因此不会进行类型检查。
  • @drquicksilver 您的答案可以编译,但是当我运行程序时,它会正常退出,而不会在屏幕上显示任何内容。发生的情况是我在输入文本并调用 runCompiler 后点击了转义,然后它正常结束,没有任何输出。
  • @StuartPaton Well Lee 已将他的答案编辑成相当完整的内容;如果你在屏幕上看不到任何东西,那么制作 compileProc 会产生一个空字符串,或者它可能永远不会被调用。我会查看 Lee 的回答和/或提供更多关于您实际调用的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-15
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多