比较一个 IO String 与一个 String,如果不相等则打印一条消息,并返回该值。

huangapple go评论58阅读模式
英文:

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

问题

以下是你要的翻译部分:

我不确定以前是否有人提过这个问题,但是我从Google上没有找到任何信息
我想在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类型还是非IO类型有关

thing.hs:7:3: 错误:
 无法匹配预期类型‘IO Bool’与实际类型‘Bool
 在‘do’块的语句中:
   (string == input) || (putStrLn "Not hello" >> False)
 在表达式中:
   do putStr "Input:"
      hFlush stdout
      input <- getLine
      (string == input) || (putStrLn "Not hello" >> False)
 在‘inputThing’的等式中:
   inputThing string
     = do putStr "Input:"
          hFlush stdout
          input <- getLine
          ....
|
7 |   (string == input) || (putStrLn "Not hello" >> False)
|   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:25: 错误:
 无法匹配预期类型‘Bool’与实际类型‘IO b0
 在‘(||)’的第二个参数中,即
   (putStrLn "Not hello" >> False)
 在‘do’块的语句中:
   (string == input) || (putStrLn "Not hello" >> False)
 在表达式中:
   do putStr "Input:"
      hFlush stdout
      input <- getLine
      (string == input) || (putStrLn "Not hello" >> False)
|
7 |   (string == input) || (putStrLn "Not hello" >> False)
|                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:49: 错误:
 无法匹配预期类型‘IO b0’与实际类型‘Bool
 在‘(>>)’的第二个参数中,即‘False
 在‘(||)’的第二个参数中:
   (putStrLn "Not hello" >> False)
 在‘do’块的语句中:
   (string == input) || (putStrLn "Not hello" >> False)
 在表达式中:
   do putStr "Input:"
      hFlush stdout
      input <- getLine
      (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: 错误:
 无法匹配预期类型‘IO Bool’与实际类型‘Bool
 在‘do’块的语句中:
   (fmap ((==) string) input)
     || (putStrLn "Not hello" >> return False)
 在表达式中:
   do putStr "Input:"
      hFlush stdout
      input <- getLine
      (fmap ((==) string) input)
        || (putStrLn "Not hello" >> return False)
 在‘inputThing’的等式中:
   inputThing string
     = do putStr "Input:"
          hFlush stdout
          input <- getLine
          ....
|
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
|   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:4: 错误:
 无法匹配预期类型‘Bool’与实际类型‘[Bool]
 在‘(||)’的第一个参数中,即
   (fmap ((==) string) input)
 在‘do’块的语句中:
   (fmap ((==) string) input)
     || (putStrLn "Not hello" >> return False)
 在表达式中:
   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: 错误:
 无法匹配类型‘Char’与‘[Char]
 预期:[String]
 实际:String
 在‘fmap’的第二个参数中,即‘input
 在‘fmap’的第一个参数中,即‘(fmap ((==) string) input)
 在‘(&&)’的第一个参数中,即
   (fmap ((==) string) input)
 在‘do’块的语句中:
   (fmap ((==) string)

<details>
<summary>英文:</summary>

I don&#39;t know if this has been asked before, but I haven&#39;t got anywhere from Googling.
I want to have the following code&#39;s equivalent in Haskell:
```python
def inputThing(string: str) -&gt; bool:
  a=input(&quot;Input: &quot;)
  if a==&quot;Hello&quot;:
    return True
  else:
    print(&quot;Not hello&quot;)
    return False

What I came up with is something like this:

import System.IO ( hFlush, stdout )
inputThing :: String -&gt; IO Bool
inputThing string = do
  putStr &quot;Input:&quot;
  hFlush stdout
  input &lt;- getLine
  if string == input then True else putStrLn &quot;Not hello&quot; &gt;&gt; False

that last line I simplified to (or rather the linter suggested)

(string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)

But I get various errors that all seem to have something to do with things being IO typed or not:

thing.hs:7:3: error:
     Couldn&#39;t match expected type IO Bool with actual type Bool
     In a stmt of a &#39;do&#39; block:
        (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
      In the expression:
        do putStr &quot;Input:&quot;
           hFlush stdout
           input &lt;- getLine
           (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
      In an equation for inputThing:
          inputThing string
            = do putStr &quot;Input:&quot;
                 hFlush stdout
                 input &lt;- getLine
                 ....
  |
7 |   (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:25: error:
     Couldn&#39;t match expected type Bool with actual type IO b0
     In the second argument of (||), namely
        (putStrLn &quot;Not hello&quot; &gt;&gt; False)
      In a stmt of a &#39;do&#39; block:
        (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
      In the expression:
        do putStr &quot;Input:&quot;
           hFlush stdout
           input &lt;- getLine
           (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
  |
7 |   (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
  |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:49: error:
     Couldn&#39;t match expected type IO b0 with actual type Bool
     In the second argument of (&gt;&gt;), namely False
      In the second argument of (||), namely
        (putStrLn &quot;Not hello&quot; &gt;&gt; False)
      In a stmt of a &#39;do&#39; block:
        (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
  |
7 |   (string == input) || (putStrLn &quot;Not hello&quot; &gt;&gt; False)
  |                                                 ^^^^^

The best I could think of was:

(fmap ((==) string) input) || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)

This still doesn't work:

thing.hs:7:3: error:
     Couldn&#39;t match expected type IO Bool with actual type Bool
     In a stmt of a &#39;do&#39; block:
        (fmap ((==) string) input)
          || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
      In the expression:
        do putStr &quot;Input:&quot;
           hFlush stdout
           input &lt;- getLine
           (fmap ((==) string) input)
             || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
      In an equation for inputThing:
          inputThing string
            = do putStr &quot;Input:&quot;
                 hFlush stdout
                 input &lt;- getLine
                 ....
  |
7 |   (fmap ((==) string) input) || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:4: error:
     Couldn&#39;t match expected type Bool with actual type [Bool]
     In the first argument of (||), namely
        (fmap ((==) string) input)
      In a stmt of a &#39;do&#39; block:
        (fmap ((==) string) input)
          || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
      In the expression:
        do putStr &quot;Input:&quot;
           hFlush stdout
           input &lt;- getLine
           (fmap ((==) string) input)
             || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
  |    ^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:23: error:
     Couldn&#39;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 &#39;do&#39; block:
        (fmap ((==) string) input)
          || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
  |                       ^^^^^

thing.hs:7:34: error:
     Couldn&#39;t match expected type Bool with actual type IO Bool
     In the second argument of (||), namely
        (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
      In a stmt of a &#39;do&#39; block:
        (fmap ((==) string) input)
          || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
      In the expression:
        do putStr &quot;Input:&quot;
           hFlush stdout
           input &lt;- getLine
           (fmap ((==) string) input)
             || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn &quot;Not hello&quot; &gt;&gt; return False)
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

At this point I thought "Surely there's a much simpler way of doing this I haven't thought of" but as previously mentioned, Googling wasn't getting me far, so I decided to post this.

I am very certain it is the case that you cannot convert an IO String to a String - but I'm guessing there's a way to get a IO Bool that returns the comparison of an IO String to a String - however, as shown, I didn't get anywhere with it.

答案1

得分: 3

TrueFalse 的类型是 Bool,但结果需要是 IO Bool 类型。这种情况下,存在一个易于理解的转换方式(与 IO Bool 转为 Bool 不同,后者不可行):这就是 return 的作用!因此,它实际上看起来更类似于 Python:

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

或者更简洁的,适用于 applicative 风格:

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

True and False have type Bool, but the result needs to be of type IO Bool. This way, there's actually an easy and sensible conversion (unlike IO Bool to Bool, which is not possible): this is what return does! So it actually looks more similar to Python:

   if string == input
then return True
else putStrLn &quot;Not hello&quot; &gt;&gt; return False

or, depending on your taste in code layout

   if string == input then
return True
else do
putStrLn &quot;Not hello&quot;
return False

or shorter, applicative-style:

   if string == input
then pure True
else False &lt;$ putStrLn &quot;Not hello&quot;

答案2

得分: 1

The linter put you on the wrong path. All you need to do is add a pure or two:

(代码部分未翻译)

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

英文:

The linter put you on the wrong path. All you need to do is add a pure or two:

import System.IO ( hFlush, stdout )
inputThing :: String -&gt; IO Bool
inputThing string = do
putStr &quot;Input:&quot;
hFlush stdout
input &lt;- getLine
if string == input then pure True else putStrLn &quot;Not hello&quot; &gt;&gt; pure False

huangapple
  • 本文由 发表于 2023年4月4日 05:05:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75923764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定