2016-11-22 18 views
3

Я пытаюсь сделать JSON синтаксический в IO:Haskell эсон: Как получить значение из Parser в IO монаде

{-# LANGUAGE OverloadedStrings #-} 
import Network.HTTP.Simple 
import Data.Aeson 
import Data.Maybe (fromJust) 

main :: IO() 
main = do 
    response <- getResponseBody <$> httpJSON "http://localhost:9200" :: IO Object 
    name <- fromJust <$> response .: "name" :: Parser String 
    print "hi" 

Я получаю ошибку:

/home/nut/dev/haskell/elastic/app/Main.hs:39:11: error: 
    • Couldn't match type ‘Parser’ with ‘IO’ 
     Expected type: IO String 
     Actual type: Parser String 
    • In a stmt of a 'do' block: 

Так как я получить name из результата json?

+2

Похоже, вы пытаетесь связать результат 'fromJust <$> ответ:. "Название"' в 'IO', но это просто значение« Parser ». Я не очень хорошо знаком с Aeson, но думаю, вам нужно запустить парсер (чисто) с помощью Data.Aeson.Types.parse или 'parseMaybe'. –

ответ

3

эсон имеет кучу функций, чтобы перейти от Parser a к a:

parse  :: (a -> Parser b) -> a -> Result b 
parseEither :: (a -> Parser b) -> a -> Either String b 
parseMaybe :: (a -> Parser b) -> a -> Maybe b 

так что если у вас есть, например,

(.: "name") :: Object -> Parser String 

то есть

parseMaybe (.: "name") :: Object -> Maybe String 

так что вы можете сделать

{-# LANGUAGE OverloadedStrings #-} 
import Network.HTTP.Simple 
import Data.Aeson 
import Data.Maybe (fromJust) 
import Data.Aeson.Types -- new import for parseMaybe 

main :: IO() 
main = do 
    response <- getResponseBody <$> httpJSON "http://localhost:9200" 
    let name = fromJust $ parseMaybe (.: "name") response :: String 
    print "hi" 
+0

Теперь я немного смущен. не будет ли это '(.:" name ") :: Value -> Parser String'? Тип 'Object' -' Value'? Извините за то, что вы смутили библиотеку Aeson ... – LudvigH

+0

Да, это правильно. Все выражение 'fromJust $ parseMaybe (.:" Name ") response' - это то, что мы комментируем как имеющее тип' String': '(.:" Name ") :: Value -> Parser String' и' response :: Value ', поэтому мы можем применить' parseMaybe :: (a -> Parser b) -> a -> Maybe b' с 'a ~ Value' и' b ~ String'. – Cactus

+1

Конечно, если мы просто использовали 'name' для чего-либо вообще (например, изменив последнюю строку с' print 'hi "' на 'putStrLn $ unwords [" Hi, ", name]'), которая предписывает его тип, тогда мы не требуется аннотация типа в строке 'let name = ...'. – Cactus