2

我试图围绕 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

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

4

2 回答 2

8

您意识到您正在尝试将 aMaybe与 a 匹配是正确的IO。对于要进行类型检查的 bind ( >>=) 运算符,两个 Monad 应该相同。解决此问题的一种方法是使用以下方法将 monad 包装MaybeIOmonad 中return

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

或者更简单地说:

return (myFunc "yo") >>= print

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

main :: IO ()
main = print . myFunc $ "yo"
于 2014-08-23T00:37:51.023 回答
3

转换Maybe StringIO与将 aMaybe String转换为其他任何内容相同:您需要选择一个要映射Nothing到的值,以及一个要映射到的值Just x。由于您要映射到IO String,我假设您要映射Nothing到异常并映射Just xreturn 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

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

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

例如)。

于 2014-08-23T00:44:56.163 回答