【问题标题】:Couldn't match type ‘Either String’ with ‘[]’无法将类型“Either String”与“[]”匹配
【发布时间】:2020-12-22 03:59:04
【问题描述】:

我有这个主要方法:

main :: IO ()
main = do 
     x <- getArgs
     case x of
         [] -> putStrLn "Empty"
         [x] ->  putStrLn (split x >>= (\(a,b) -> a ++ " " ++ b))
         _ -> putStrLn "More than one argument"

其中split函数定义为:

split :: String -> Either String (String, String)

我在这里做错了什么?我在这里要做的只是打印我从split 函数返回的元组

【问题讨论】:

    标签: haskell monads


    【解决方案1】:
    putStrLn (split x >>= (\(a,b) -> a ++ " " ++ b))
    

    一元绑定运算符&gt;&gt;= 有签名

    (>>=) :: Monad m => m a -> (a -> m b) -> m b
    

    或者,在您的具体情况下,

    (>>=) :: Either e a -> (a -> Either e b) -> Either e b
    

    所以我们使用&gt;&gt;=,当我们有一个Either 并且想要将其中的东西传递给一个本身返回Either 的函数时。但是你的函数是\(a,b) -&gt; a ++ " " ++ b),它不会返回Either。您要做的是获取Either 并将函数应用到内部,而单独留下Either 部分。这是对Functor 类型类中的fmap 的使用。

    fmap :: Functor f => (a -> b) -> f a -> f b
    -- Specifically
    fmap :: (a -> b) -> Either e a -> Either e b
    

    所以你想要

    fmap (\(a,b) -> a ++ " " ++ b) $ split x
    

    这将返回一个Either String StringputStrLn 可以打印字符串。如果我们要打印Either,那么你需要使用print

    print (fmap (\(a,b) -> a ++ " " ++ b) $ split x)
    

    另一方面,我们可以对结果进行模式匹配,并在 Left 情况下做一些不同的事情。

    case fmap (\(a,b) -> a ++ " " ++ b) $ split x of
      Left e -> undefined -- Error case
      Right s -> putStrLn s
    

    【讨论】:

    • 感谢您对单子的澄清。我真的很欣赏这个准确的答案!
    • 别担心! Haskell 中可用的不同类型的抽象乍一看肯定像符号汤。只要记住在学习的同时依赖类型系统来指导你,最终不同的操作将成为第二天性。祝你好运! :)
    猜你喜欢
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多