【问题标题】:Haskell monad return typeHaskell monad 返回类型
【发布时间】:2013-05-09 08:09:07
【问题描述】:

我正在尝试做一些编程,但我无法进入 monad。我在 IO 功能方面进步了一点,但现在我肯定迷路了……

我有一个从网络加载的 XML 字符串(所以它“存储”在 IO String 中)。因此,我需要一个do 块来加载到普通字符串。

foo :: IO String -> Nothing
foo xmlio = do
    xmlio <- xml
    -- do some magic

我已经实现了另一个函数,它接受纯字符串并返回纯 XML 元素。它做了更多,但让我们简化一下,因为它对这个问题并不重要。

import Text.XML.Light
import Text.XML.Light.Input

toxml :: String -> Maybe Element
toxml s = parseXMLDoc s

现在我尝试将这两者结合起来接受一个 IO 字符串并返回一个“IO 元素”。

toxmlio :: IO String -> ??? Maybe Element
toxmlio s = do
    pures <- s
    let toReturn = parseXMLDoc s
    return s

返回函数的类型是(根据ghci):

let foo = "<foo>bar</foo>"
:t return (parseXMLDoc foo)
    >> return (parseXMLDoc foo) :: Monad m => m (Maybe Element)

但如果我将函数的标题更改为

toxmlio :: IO String -> Monad (Maybe Element)
toxmlio s = do
    pures <- s
    let toReturn = parseXMLDoc s
    return s

我得到一个编译错误

Kind mis-match
The first argument of `Monad' should have kind `* -> *',
but `Maybe Element' has kind `*'
In the type signature for `xmlio':
  xmlio :: String -> Monad (Maybe Element)

有人知道如何解决这个问题吗?还是我完全迷路了,haskell 以另一种方式做到了这一点?谢谢你的回答。

【问题讨论】:

  • 在这里定义一个带有IO String 参数的函数是错误的。 IO String 不是包裹在某些东西中的字符串,它是一个返回字符串的 procedure。例如,绑定它两次会从网络加载它两次。您通常不会编写将IO something 作为参数的函数,除非您正在编写某种控制结构。我认为如果你寻求帮助来编写你想要调用它的代码会更好。
  • 我真的只是 Haskell 的初学者,老实说,我不喜欢它的懒惰。我知道类似函数的行为。我不喜欢非常具体的主题,基本上我需要从 Internet 加载一个 XML,对其进行处理,然后根据结果我将加载另一个 XML。但是,我确实想将任务拆分为更多函数,因此我想使用 IO 输入来实现这些方法(因为最内部函数返回 IO,我无法摆脱它)。那么,有一个单独的do 来处理输入、包装 IO 并正常调用其他函数会更好吗?
  • 是的。保持尽可能多的代码纯净。它既更易于使用和理解,也更易于在解释器中测试您的函数。
  • 非常感谢您的提示。

标签: haskell io monads


【解决方案1】:

看起来像你想要的:

toxmlio :: IO String -> IO (Maybe Element)
toxmlio s = do
    pures <- s
    let toReturn = parseXMLDoc pures
    return toReturn

但是你可以使用liftM:

toxmlio :: IO String -> IO (Maybe Element)
toxmlio = liftM parseXMLDoc

你可以让它更通用,因为 liftM 不依赖于特定的 monad 类型:

toxmlio :: Monad m => m String -> m (Maybe Element)
toxmlio = liftM parseXMLDoc

【讨论】:

  • 感谢您的回答,此解决方案有效,但我宁愿遵循 hammar 的建议。无论如何我都接受这个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-15
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
相关资源
最近更新 更多