【问题标题】:Couldn't match expected type ‘IO [String]’ with actual type ‘[String]’无法将预期类型“IO [String]”与实际类型“[String]”匹配
【发布时间】:2019-05-11 17:32:37
【问题描述】:

我有这两个代码 sn-ps,我猜它们会做同样的事情,但他们没有。这是为什么呢?

这个很好用:

fdup :: String -> IO ()
fdup filename = do
        h <- openFile filename ReadMode
        c <- hGetContents h
        putStr $ unlines $ parse $ lines c
        hClose h

这个返回错误Couldn't match expected type ‘IO [String]’ with actual type ‘[String]’:

fdup' :: String -> IO ()
fdup' filename = do
        h <- openFile filename ReadMode
        c <- hGetContents h
        ls <- lines c
        putStr $ unlines $ parse $ ls
        hClose h

parse :: [String] -&gt; [String]

它们有什么区别?

【问题讨论】:

  • 错误可能位于ls &lt;- lines c?
  • 是的,但我不明白为什么......
  • 因为如果你写x &lt;- some_expr,那么some_expr需要是Monad m =&gt; m a类型,然后xa类型。在整个do 块中,一个使用相同的单子m。不幸的是,do 表示法可能表明这只是一种不同的“风格”。但实际上这里的 monad 发挥了作用。简而言之,Haskell 是一种函数式语言,使用相同参数的调用总是给出相同的结果。有状态的动作,如打开文件等,因此需要一个状态。 monad 可以用于隐式传递该状态。
  • 现在我清楚了,谢谢你的解释!
  • @WillNess 为什么要涉及&lt;-return?为什么不只是let ls = lines c

标签: haskell io-monad


【解决方案1】:

正如 Willem Van Onsem 所解释的,您不需要在那个特定位置使用 &lt;-,因为 lines c 只是一个字符串列表,而不是 IO 计算。如果你想给它一个名字,你可以使用 let-binding 代替:

fdup' :: String -> IO ()
fdup' filename = do
        h <- openFile filename ReadMode
        c <- hGetContents h
        let ls = lines c
        putStr $ unlines $ parse $ ls
        hClose h

【讨论】:

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