如何将 IO 字符串与字符串进行比较,如果为 false,则打印消息并返回值?

How do I compare an IO String with a String, print a message if false, and return the value?

提问人:Electroboss 提问时间:4/4/2023 最后编辑:duplodeElectroboss 更新时间:4/4/2023 访问量:84

问:

我不知道以前是否有人问过这个问题,但我没有从谷歌搜索中得到任何东西。 我想在 Haskell 中拥有以下代码的等效项:

def inputThing(string: str) -> bool:
  a=input("Input: ")
  if a=="Hello":
    return True
  else:
    print("Not hello")
    return False

我想出的是这样的:

import System.IO ( hFlush, stdout )
inputThing :: String -> IO Bool
inputThing string = do
  putStr "Input:"
  hFlush stdout
  input <- getLine
  if string == input then True else putStrLn "Not hello" >> False

我简化的最后一行(或者更确切地说是 linter 建议的)

(string == input) || (putStrLn "Not hello" >> False)

但是我收到各种错误,这些错误似乎都与IO类型与否有关:

thing.hs:7:3: error:
    • Couldn't match expected type ‘IO Bool’ with actual type ‘Bool’
    • In a stmt of a 'do' block:
        (string == input) || (putStrLn "Not hello" >> False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (string == input) || (putStrLn "Not hello" >> False)
      In an equation for ‘inputThing’:
          inputThing string
            = do putStr "Input:"
                 hFlush stdout
                 input <- getLine
                 ....
  |
7 |   (string == input) || (putStrLn "Not hello" >> False)
  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:25: error:
    • Couldn't match expected type ‘Bool’ with actual type ‘IO b0’
    • In the second argument of ‘(||)’, namely
        ‘(putStrLn "Not hello" >> False)’
      In a stmt of a 'do' block:
        (string == input) || (putStrLn "Not hello" >> False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (string == input) || (putStrLn "Not hello" >> False)
  |
7 |   (string == input) || (putStrLn "Not hello" >> False)
  |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:49: error:
    • Couldn't match expected type ‘IO b0’ with actual type ‘Bool’
    • In the second argument of ‘(>>)’, namely ‘False’
      In the second argument of ‘(||)’, namely
        ‘(putStrLn "Not hello" >> False)’
      In a stmt of a 'do' block:
        (string == input) || (putStrLn "Not hello" >> False)
  |
7 |   (string == input) || (putStrLn "Not hello" >> False)
  |                                                 ^^^^^

我能想到的最好的是:

(fmap ((==) string) input) || (putStrLn "Not hello" >> return False)

这仍然不起作用:

thing.hs:7:3: error:
    • Couldn't match expected type ‘IO Bool’ with actual type ‘Bool’
    • In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (fmap ((==) string) input)
             || (putStrLn "Not hello" >> return False)
      In an equation for ‘inputThing’:
          inputThing string
            = do putStr "Input:"
                 hFlush stdout
                 input <- getLine
                 ....
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:4: error:
    • Couldn't match expected type ‘Bool’ with actual type ‘[Bool]’
    • In the first argument of ‘(||)’, namely
        ‘(fmap ((==) string) input)’
      In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (fmap ((==) string) input)
             || (putStrLn "Not hello" >> return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |    ^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:23: error:
    • Couldn't match type ‘Char’ with ‘[Char]’
      Expected: [String]
        Actual: String
    • In the second argument of ‘fmap’, namely ‘input’
      In the first argument of ‘(||)’, namely
        ‘(fmap ((==) string) input)’
      In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |                       ^^^^^

thing.hs:7:34: error:
    • Couldn't match expected type ‘Bool’ with actual type ‘IO Bool’
    • In the second argument of ‘(||)’, namely
        ‘(putStrLn "Not hello" >> return False)’
      In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (fmap ((==) string) input)
             || (putStrLn "Not hello" >> return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

在这一点上,我想“肯定有一种我没有想到的更简单的方法来做到这一点”,但如前所述,谷歌搜索并没有让我走得太远,所以我决定发布这个。

我非常确定您无法将 IO 字符串转换为字符串 - 但我猜有一种方法可以获得 IO 布尔值,该布尔值返回 IO 字符串与字符串的比较 - 但是,如图所示,我没有得到它。

Haskell 类型 IO

评论


答:

1赞 Noughtmare 4/4/2023 #1

棉绒让你走上了错误的道路。您需要做的就是添加一两个:pure

import System.IO ( hFlush, stdout )
inputThing :: String -> IO Bool
inputThing string = do
  putStr "Input:"
  hFlush stdout
  input <- getLine
  if string == input then pure True else putStrLn "Not hello" >> pure False

评论

0赞 Electroboss 4/4/2023
但是怎么办?pure
1赞 Noughtmare 4/4/2023
在本例中,它将 a 更改为BoolIO Bool
0赞 Electroboss 4/4/2023
那么 和 和有什么不一样呢?purereturn
3赞 Noughtmare 4/4/2023
它基本上是同一事物的不同名称。从技术上讲,它是 typeclass 的一个方法,并且是一个需要 的函数,所以它更通用一些。但我也更愿意避免与命令式语言的关键字混淆(这有微妙的不同)。pureApplicativereturnMonadpurepurereturn
3赞 leftaroundabout 4/4/2023 #2

True并具有类型,但结果必须为 类型 。这样,实际上有一个简单而明智的转换(与 不同,这是不可能的):这就是 return 的作用!所以它实际上看起来更类似于 Python:FalseBoolIO BoolIO BoolBool

   if string == input
    then return True
    else putStrLn "Not hello" >> return False

或者,取决于你对代码布局的喜好

   if string == input then
       return True
    else do
       putStrLn "Not hello"
       return False

或更短的应用式:

   if string == input
    then pure True
    else False <$ putStrLn "Not hello"