2014-01-22 48 views
4

假設這YAML對象的讀取YAML列表(保存在一個名爲users.yml):在Haskell

- id: 1 
    name: Unknown user 
    reputation: 0 

- id: 2 
    name: Foo bar 
    reputation: 4 

而這哈斯克爾data類型:

data MyUser = MyUser {id :: Int, 
         name :: String, 
         reputation :: Int} 
         deriving (Show) 

我想用yaml庫閱讀YAML到[MyUser]。我怎樣才能做到這一點?

回答

11

你需要創建一個FromJSON實例(注意,FromJSON作爲YAMLAeson庫導出這就是所謂的),如Data.Yaml documentation描述。

類似的問題與埃宋以前討論here而哈斯克爾YAML庫的選擇進行了討論here

下面是該YAML文件轉換成[MyUser]最小工作示例:

{-# LANGUAGE OverloadedStrings #-} 
import Data.Yaml 
import Control.Applicative -- <$>, <*> 
import Data.Maybe (fromJust) 

import qualified Data.ByteString.Char8 as BS 

data MyUser = MyUser {id :: Int, 
         name :: String, 
         reputation :: Int} 
         deriving (Show) 

instance FromJSON MyUser where 
    parseJSON (Object v) = MyUser <$> 
          v .: "id" <*> 
          v .: "name" <*> 
          v .: "reputation" 
    -- A non-Object value is of the wrong type, so fail. 
    parseJSON _ = error "Can't parse MyUser from YAML/JSON" 

main = do 
     ymlData <- BS.readFile "users.yml" 
     let users = Data.Yaml.decode ymlData :: Maybe [MyUser] 
     -- Print it, just for show 
     print $ fromJust users 
+0

我可以't get this work:'/app/Main.hs:21:5:error: •無法將類型'Yaml.Value'與'[Char]'相匹配 預期類型:unordered-containers-0.2.8.0 :Data.HashMap.Base.HashMap text-1.2 .2.1:Data.Text.Internal.Text字符串 實際類型:Yaml.Object •在'(<$>)'的第二個參數中,即'v' 在'(。:)'的第一個參數中,即'交易<$> v' 在'(。:)'的第一個參數中,即 '(。:)交易<$> v「entryDate」<*> v'' – adius

+0

@adius我無法複製。 'cabal sandbox init; cabal安裝yaml; cabal exec runghc index.hs'其中'index.hs'是答案中列出的代碼正確產生'[MyUser {id = 1,name =「未知用戶」,信譽= 0},MyUser {id = 2,name = 「Foo bar」,聲譽= 4}]'對我來說。也許你可以嘗試'cabal update'並更改軟件包版本? –

+0

問題是我沒有從Data.Yaml中導入'。:'。我認爲這是一個由'Control.Applicative'輸出的函數。不幸的是編譯器錯誤在這方面並不真正有用 – adius