1

我是 Haskell 的新手,在从 url 解析 JSON 时遇到了一些麻烦。我已经设法对事物的解析方面进行编码,并使用字符串进行了测试,它们工作正常。我遇到的麻烦是当我开始使用 IO 时。

我有以下代码:

data Movie = Movie 
    { adult :: Bool, 
      backdrop_path :: Maybe String,
      id :: Int,
      original_title :: String,
      release_date :: String,
      poster_path :: Maybe String,
      popularity :: Int, 
      title :: String,
      vote_average :: Double,
      vote_count :: Int
    } deriving (Show)

data MovieList = MovieList {getMovies ::[Movie]} deriving (Show)

instance FromJSON Movie where
    parseJSON (Object v) = Movie <$>
                   (v .: "adult") <*>
                   (v .:? "backdrop_path") <*> -- Optional
                   (v .: "id") <*>
                   (v .: "original_title") <*>
                   (v .: "release_date") <*>
                   (v .:? "poster_path") <*> -- Optional
                   (v .: "popularity") <*>
                   (v .: "title") <*>
                   (v .: "vote_average") <*>
                   (v .: "vote_count")

instance FromJSON MovieList where
    parseJSON (Object o) = MovieList <$> o .: "results"
    parseJSON _          = mzero

movieAPIRequest :: String -> IO String
movieAPIRequest movieURI =
    do resp <- simpleHTTP request
       case resp of
         Left x -> return $ "Error connecting: " ++ show x
         Right r ->
             case rspCode r of
               (2,_,_) -> return $ rspBody r -- Request Fulfilled
               _ -> return $ show r -- Request Failed
    where request = Request {rqURI = uri, rqMethod = GET, rqHeaders = [], rqBody = ""}
          uri = fromJust $ parseURI movieURI

convertToByteString s = BS.pack s

main = do
    response <- movieAPIRequest url 
    decoded <- decode (convertToByteString response):: Maybe MovieList
    return $ decoded

我无法让主要工作。我想从 url 中自动检索 JSON。给我请求的movieAPIRequest主体(JSON)为IO String. convertToByteString接受一个字符串并转换为 Data.ByteString.Lazy.Char8.ByteString,因为 Aeson 中的decode函数接受一个字节串作为参数。使用上面的代码,我收到以下错误:

[1 of 1] 编译 MovieDataType(MovieDataType.hs,解释)

MovieDataType.hs:62:20:
    Couldn't match type `Maybe' with `IO'
    Expected type: IO MovieList
      Actual type: Maybe MovieList
    In a stmt of a 'do' block:
      decoded <- decode (convertToByteString response) :: Maybe MovieList
    In the expression:
      do { response <- movieAPIRequest url;
           decoded <- decode (convertToByteString response) ::
                        Maybe MovieList;
           return $ decoded }
    In an equation for `main':
        main
          = do { response <- movieAPIRequest url;
                 decoded <- decode (convertToByteString response) ::
                              Maybe MovieList;
                 return $ decoded }
Failed, modules loaded: none.

我已经尝试修复它,但不断变得不同,我无法理解。例如,这个告诉它期望的 IO MovieList 但解码应该返回一个 Maybe MovieList。

4

1 回答 1

1

我在您的主要功能中看到了几个错误

main = do
    response <- movieAPIRequest url 
    decoded <- decode (convertToByteString response):: Maybe MovieList
    return $ decoded

首先,如果您在http://hackage.haskell.org/package/aeson-0.6.1.0/docs/Data-Aeson.html查找“解码” ,您会看到它的类型

decode :: FromJSON a => ByteString -> Maybe a

请注意,此定义中不涉及任何 IO,因此您不能使用“<-”从中提取任何数据。相反,请使用“让解码 = ....”。

当你学习更多 Haskell 时,你可以阅读这种区别背后的理论,但是现在,请注意,如果一个函数返回类型 IO a,你可以使用 "value <- function x y" 从中提取数据(这就是为什么 movieAPIRequest很好),而如果函数没有副作用,则使用“let value = function x y”提取值。(它比这更复杂,但这是 90% 的答案,可以让你继续学习,直到你了解单子)。

其次,您从 main 返回一个 IO() 类型的值。这是任何 Haskell 程序中 main 的硬编码类型,因此您不能返回除“()”之外的任何值。相反,您必须在程序结束之前对值“decoded”(例如打印它)做一些事情。

于 2013-12-13T01:43:27.393 回答