0

我正在尝试做一些编程,但我无法进入单子。我在 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 以另一种方式做到了这一点?谢谢您的回答。

4

1 回答 1

3

看起来你想要:

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
于 2013-05-14T21:57:15.627 回答