2

Haskell 的 Text.JSON 库使用一种称为 Result 的抽象数据类型,它基本上是它们的 Maybe 形式,但不是 Nothing,而是 Error String。Anywho,我需要使用 liftIO 将返回 IO 事物的函数调用转换为 JSON.readJSON 实现中的 Result 事物。我是 monad 转换器的新手,似乎无法为 Result 实现 liftIO(根据 ghci,我一直在尝试构建无限类型)。

有任何想法吗?

非常感谢

编辑

对不起,我花了这么长时间来详细说明!我很感激你们的帮助。

  readJSON (JSObject obj) = do text <- getVal obj "text"
                           user <- getVal obj "from_user"
                           iden <- getVal obj "id_str"
                           url <- (do if (length.extractURLs) text == 0
                                           then return ""
                                           else return $ head $ extractURLs text)
                           title <- liftIO (getSiteTitle url)
                           return $ 
                            Tweet 
                              NewsStory {
                                          title = "Twitter",
                                          desc = text,
                                          url = url,
                                          metric = 0,
                                          sourceURL = "twitter.com/" ++ user  ++ "/status/" ++ iden
                                        }

因此,return 之前的最后一行使用 getSiteTitle 来解析位于该 url 的网站以获取其标题。但是,该函数返回一种 IO String 类型,编译器告诉我它希望它是 Result。这是不可能的吗?

再次感谢!

编辑2

我决定从我的数据类型中删除标题,稍后在 IO monad 中获取它。感谢大家的帮助!我当然从这个问题中学到了东西。

4

3 回答 3

5

您不能在 readJSON 中使用 IO(不使用 unsafePerformIO)。当您有一堆底部带有 IO 的 monad 转换器时,使用 liftIO 。也许如果您提供有关您要实现的目标的更具体信息,您将能够获得更有用的答案:)

于 2010-11-14T08:02:33.703 回答
2

你想要的是不可能的。在 json 包中,readJSON :: JSValue -> Result a. 根据定义,这是一个纯函数。可以说,您可以将结果实例化为带有IOinside 的东西,但这样就不可能实现showJSON :: a -> JSValue.

我的解决方案?我会给你的数据类型 atitle :: Maybe String然后在 IO 中进行第二次填充标题。

于 2010-11-14T19:58:21.570 回答
1

你没有说你正在使用哪个特定的 JSON 库,并且有几十个具有相似的名称和命名空间......

因为您想使用 IO 来获取 url,所以您必须将您的函数分成两个函数,一个在 JSON monad 中,一个在 IO monad 中。因为您不能“运行” IO monad,所以您必须在 IO 中运行 JSON monad,这里 doAll 是结合两者的进一步函数。

您将不得不对其进行一些编辑以使其与您正在使用的 JSON 库相匹配 - 一些类型签名未填写,我不知道 JSON monad 的“运行”函数和返回类型是什么:

-- This one is in the JSON monad...
-- The type sig needs fixing...
readJSON :: JSObject ?? -> GetJSON (String,String,String,String)
readJSON (JSObject obj) = do 
    text <- getVal obj "text"
    user <- getVal obj "from_user"
    iden <- getVal obj "id_str"
    url <- (do if (length.extractURLs) text == 0
               then return ""
               else return $ head $ extractURLs text)
    return (text,user,iden,url)

-- This one is in IO...
ioStep :: (String,String,String,String) -> IO TweetNewsStory
ioStep (text,user,iden,url) = do
  title <- getSiteTitle url
  return $ TweetNewsStory {
             title = "Twitter",
             desc = text,
             url = url,
             metric = 0,
             sourceURL = "twitter.com/" ++ user  ++ "/status/" ++ iden
           }


-- Type sig needs fixing...
-- The JSON library will provide something similar to
-- runJSON...
--
doAll :: JSObject ?? -> IO TweetNewsStort
doAll jsobj = 
    let ans = runJSON $ readJSON jsobj in 
     case ans of 
       Left err -> error $ err
       Right val -> ioStep val
于 2010-11-14T15:49:24.373 回答