【问题标题】:"Couldn't match type `Maybe' with `IO' Expected type: IO String Actual type: Maybe String" In Haskell“无法将类型'Maybe'与'IO'匹配预期类型:IO String实际类型:Maybe String”在Haskell中
【发布时间】:2014-08-23 00:24:38
【问题描述】:

我正试图围绕 Monads 进行思考,并觉得如果我能解释为什么它不能编译,我会有更好的理解。

module Main where
import Data.Maybe
import System.Environment

myFunc :: String-> Maybe String
myFunc x = Just x

main :: IO ()
main = myFunc "yo" >>= putStrLn 

我得到的错误是

blah.hs:9:10:
    Couldn't match type `Maybe' with `IO'
    Expected type: IO String
      Actual type: Maybe String
    In the return type of a call of `myFunc'
    In the first argument of `(>>=)', namely `myFunc "yo"'
    In the expression: myFunc "yo" >>= putStrLn

我意识到问题在于我正在尝试将 MaybeIO 匹配,但我不完全确定如何将 Maybe'd 变量转换为 IO。任何帮助将不胜感激!

【问题讨论】:

    标签: haskell monads maybe


    【解决方案1】:

    您正确地意识到您正在尝试将MaybeIO 匹配。对于要进行类型检查的绑定 (>>=) 运算符,两个 Monad 应该相同。解决此问题的一种方法是使用 returnMaybe 包装在 IO monad 中:

    return (myFunc "yo") >>= putStrLn . show
    

    或者更简单地说:

    return (myFunc "yo") >>= print
    

    话虽如此,您并不需要所有花哨的 monad 运算符。这应该很简单:

    main :: IO ()
    main = print . myFunc $ "yo"
    

    【讨论】:

    • 我不知道 print 可以将 Maybe String 作为参数。
    • @Tombert print 定义为 putStrLn . show。所以它可以采用任何定义了Show 实例的类型!
    • 有没有办法让控制台不输出 Just "yo" 而输出 "yo"?
    • @Tombert 那么你想为Nothing 打印什么?
    • @Tombert 一种方法是按照您的意愿这样做:main = print $ maybe "" id (myFunc "yo")。这将打印yo 而不是Just "yo"
    【解决方案2】:

    Maybe String 转换为IO 与将Maybe String 转换为任何其他值相同:您需要选择一个值以将Nothing 映射到,并选择一个值将每个Just x 映射到。既然您想映射到IO String,我假设您想将Nothing 映射到异常,并将Just x 映射到return x

    import Control.Exception
    
    data NoString = NoString deriving (Typeable, Show)
    instance Exception NoString
    
    maybeToIO :: Maybe String -> IO String
    maybeToIO Nothing = throwIO NoString
    maybeToIO (Just x) = return x
    
    main = maybeToIO (myFunc "yo") >>= putStrLn
    

    但是,我怀疑在实际应用程序中,您可能希望将Nothing 映射到定义的行为;可能什么也不打印,例如:

    main = case myFunc "yo" of
        Nothing -> return ()
        Just x -> putStrLn x
    

    基本上,不要太拘泥于MaybeIO 都是单子的事实; monad 操作只是制作这些类型值的方法;一旦获得了 Maybe 值,您仍然需要将它们作为普通数据结构进行处理(尽管 Haskell 确实有很棒的方法:

    main = maybe (return ()) putStrLn $ myFun "yo"
    

    例如)。

    【讨论】:

      猜你喜欢
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 2017-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多