反转 Return 类型 IO Bool 的值

Invert Return Value of Type IO Bool

我有一个 returns 类型 IO Bool 的函数。我想将此函数用作 filterM 的参数,但我实际上想做的是反转其输出。我尝试了一些达到 (not . f) 效果的东西,但是 not 并不符合 IO 的氛围。如何反转 IO Bool

这是一个最小的工作示例:

#!/usr/bin/env runhaskell
{-# LANGUAGE UnicodeSyntax #-}
module Main where
import Prelude.Unicode

userEnteredStr ∷ String → IO Bool
userEnteredStr str = do
    input ← getLine
    return (input ≡ str)

-- doesn't work. How would I write this function? 
--userDidntEnterStr ∷ String → IO Bool
--userDidntEnterStr str = not . userEnteredStr

main = do result ← userEnteredStr "y"
          print result

对不起,如果这是基本的!我在 Hoogle 上找不到类型为 IO Bool -> IO Bool 的函数,并且在我的网络搜索中也没有找到任何内容。

郑重声明,"doesn't work" 不是很有用的错误描述 :) 是语法错误吗?类型错误?它会编译并进行类型检查,但 return 值错误吗?这可能是对您的问题的最模糊的描述...并且对于任何想帮助您的人来说通常是一个非常非常大的 impairment/hurdle。

这里的主要问题是您不能将 not 应用于 IO Bool,因为 not 仅适用于 BoolIO Bool 不是 Bool,也不是 "contain a Bool",所以它不起作用也就不足为奇了。这就像尝试将 (* 2) 应用于您的狗。你的狗不是数字!

但您似乎知道如何使用 IO 中的 do 符号和绑定,所以也许您能理解为什么会这样?

userDidntEnterStr :: String -> IO Bool
userDidntEnterStr str = do
   didEnter <- userEnteredStr str
   return (not didEnter)

或者,您也可以将任何 (a -> b) 应用于 IO a 结果 以使用 [=23] 获得新的 IO b =]:

userDidntEnterStr :: String -> IO Bool
userDidntEnterStr str = fmap not (userEnteredStr str)