“无法匹配类型`可能'与'IO'预期类型:IO字符串实际类型:可能字符串”在Haskell中

时间:2014-08-23 00:24:38

标签: haskell monads maybe

我试图把我的头包裹在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中。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:7)

您认为自己试图将MaybeIO匹配是正确的。对于绑定(>>=)运算符来进行类型检查,Monad都应该是相同的。解决此问题的一种方法是使用MaybeIO包裹在return monad中:

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

或更简单:

return (myFunc "yo") >>= print

话虽这么说,你并不需要这里所有花哨的monad经营者。这应该只是工作:

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

答案 1 :(得分:3)

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这个事实感到太过分; monad操作只是制作这些类型的值的方法;一旦你获得了Maybe值,你仍然需要将它们作为普通数据结构处理(尽管Haskell确实有这样做的方法:

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