【问题标题】:How to return True or False in a do expression - Haskell如何在 do 表达式中返回 True 或 False - Haskell
【发布时间】:2018-06-27 20:03:25
【问题描述】:

我试图在这个表达式中返回 True 或 False,但是我得到了这个错误,有人能告诉我我做错了什么吗?谢谢。

module Main (main) where
import System.IO (stdout, hSetBuffering, BufferMode(NoBuffering))

main::IO()
simOuNao::String -> Bool

main = do hSetBuffering stdout NoBuffering
      putStrLn "Guess Number v1.0"
      putStrLn "======================"

simOuNao frase = do putStrLn frase
                ans <- readLn
                if ans == 'y' || ans =='Y'
                  then return True
                  else return False

错误信息:

• Couldn't match expected type ‘Bool’ with actual type ‘IO Bool’
• In a stmt of a 'do' block: putStrLn frase
  In the expression:
    do { putStrLn frase;
         ans <- readLn;
         if ans == 'y' || ans == 'Y' then return True else return False }
  In an equation for ‘simOuNao’:
      simOuNao frase
        = do { putStrLn frase;
               ans <- readLn;
               if ans == 'y' || ans == 'Y' then return True else return False }

失败,已加载模块:无。

【问题讨论】:

    标签: haskell io


    【解决方案1】:

    一次在IO,总是在IO——没有逃脱。

    simOuNao :: String -> IO Bool
    

    【讨论】:

    • unsafePerformIO :: IO a -&gt; a除外
    • @pat 在这里提请注意unsafePerformIO 与提请注意您可以通过流氓指针算法访问 C++ 类的私有元素或通过侧面访问其他用户数据的可能性一样明智 -对 CPU 的通道攻击。是的,事实证明这是可以做到的,但它是严格未定义/特定于实现的行为(因为simOuNao 确实有可观察到的副作用),初学者甚至不应该远程考虑。
    【解决方案2】:

    如果您的函数执行 I/O,则必须通过返回 IO Bool 在类型中声明它。

    simOuNao :: String -> IO Bool
    simOuNao frase = do putStrLn frase
                        ans <- readLn
                        if ans == 'y' || ans =='Y'
                          then return True
                          else return False
    

    simOuNao 的用户必须使用类似的东西

    do ...
       b <- simOuNao frase
       ... -- here b is a Bool
    

    当然,do 表达式的类型必须再次为 IO someType

    【讨论】:

      【解决方案3】:

      do expression 是一种按顺序编写一元代码的方法,使用行 let&lt;-TrueFalseBool 构造函数,并且没有 Monad 实例。有Identity BoolMaybe () 等同态类型。

      因此,给定类型声明simOuNao :: String -&gt; BoolsimOuNao 不能定义为do 表达式。鉴于您在内部使用putStrLn,它必须返回带有IO monad 的东西。所以你给出了相互矛盾的目标。 return 将值提升为一元类型。所以你写的simOuNao 版本特别需要IO monad,类型变成simOuNao :: String -&gt; IO Bool

      另一个问题是您使用了readLn。我怀疑您打算使用getLine 并检查以'y' 开头的字符串,因为用户需要输入'y' 并加上引号,因为readLn 将需要一个字符文字。

      也可以在具有非单子类型的函数中使用单子,包括像 IdentityMaybeState 这样的单子,通常使用一些 run 函数来提取结果。尤其是 IO monad 不可能做到这一点,因为它的状态不是确定性的(它代表外部世界,所以执行的所有 IO 必须从 main 委托)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-15
        • 2018-01-06
        • 1970-01-01
        • 2020-08-14
        • 2023-04-06
        • 2011-01-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多