在Haskell中阅读YAML

时间:2012-10-25 00:15:44

标签: haskell yaml

我希望让我的Haskell程序从外部文件中读取设置,以避免重新编译以进行微小更改。熟悉YAML,我认为这是一个不错的选择。现在我必须把两件放在一起。到目前为止,Google一直没有太大的帮助。

非常感谢一个处理从文件中读取和解构YAML的示例代码。

4 个答案:

答案 0 :(得分:25)

如果我对可用的软件包感兴趣,我会去hackage,查看完整的软件包列表,然后只搜索关键字。这样做会带来这些选择(以及其他一些不太引人注目的选择):

和HsSyck周围的包装器叫做yaml-light:http://hackage.haskell.org/package/yaml-light

yaml和HsSyck最近都看起来更新了,并且似乎被广泛使用的其他软件包使用。您可以通过查看反向代码来看到这一点:

在这两者中,yaml有更多的deps,但这是因为它是yesod生态系统的一部分。一个依赖于HsSyck的库是yst,我碰巧知道它是积极维护的,所以这向我表明HsSyck也很好。

我做出选择的下一步是浏览两个库的文档,看看哪个库更适合我的目的。

在这两者中,看起来HsSyck暴露了更多的结构,但没有多少其他,而yaml通过aeson提供的json编码。这向我表明,前者可能更强大,而后者更方便。

答案 1 :(得分:10)

一个简单的例子:

首先,您需要一个test.yml文件:

db: /db.sql
limit: 100

在Haskell中阅读YAML

{-# LANGUAGE DeriveGeneric #-}

import GHC.Generics
import Data.Yaml

data Config = Config { db :: String
                     , limit :: Int
                     } deriving (Show, Generic)

instance FromJSON Config

main :: IO ()
main = do
  file <- decodeFile "test.yml" :: IO (Maybe Config)
  putStrLn (maybe "Error" show file)

答案 2 :(得分:1)

使用yamlparse-applicative,您可以在static analysis-friendly way中描述YAML解析器,因此可以从解析器中免费获取YAML格式的描述。我将为此使用Matthias Braun's example format

Name: 
ABCTEST

请注意,{-# LANGUAGE ApplicativeDo, RecordWildCards, OverloadedStrings #-} import Data.Yaml import Data.Aeson.Types (parse) import YamlParse.Applicative import Data.Map (Map) import qualified Data.Text.IO as T data MyType = MyType { stringsToStrings :: Map String String , mapOfLists :: Map String [String] } deriving Show parseMyType :: YamlParser MyType parseMyType = unnamedObjectParser $ do stringsToStrings <- requiredField' "strings_to_strings" mapOfLists <- requiredField' "map_of_lists" pure MyType{..} main :: IO () main = do T.putStrLn $ prettyParserDoc parseMyType yaml <- decodeFileThrow "config/example.yaml" print $ parse (implementParser parseMyType) yaml 甚至可以在看到实例之前打印出架构:

main

答案 3 :(得分:0)

以下是使用yaml库从YAML文件中解析特定对象的方法。

让我们解析该文件的一部分,config/example.yaml

# A map from strings to strings
strings_to_strings:
      key_one: val_one
      key_two: val_two

# A map from strings to list of strings
map_of_lists:
  key_one:
      - val_one
      - val_two
      - val_three
  key_two:
      - val_four
      - val_five

# We won't parse this
not_for: us

此模块分别解析strings_to_stringsmap_of_lists并将它们放入自定义记录MyType

{-# Language OverloadedStrings, LambdaCase #-}
module YamlTests where
import           Data.Yaml                      ( decodeFileEither
                                                , (.:)
                                                , parseEither
                                                , prettyPrintParseException
                                                )
import           Data.Map                       ( Map )
import           Control.Applicative            ( (<$>) )
import           System.FilePath                ( FilePath
                                                , (</>)
                                                )

data MyType = MyType {stringsToStrings :: Map String String,
                      mapOfLists :: Map String [String]} deriving Show
type ErrorMsg = String

readMyType :: FilePath -> IO (Either ErrorMsg MyType)
readMyType file =
  (\case
      (Right yamlObj) -> do
        stringsToStrings <- parseEither (.: "strings_to_strings") yamlObj
        mapOfLists       <- parseEither (.: "map_of_lists") yamlObj
        return $ MyType stringsToStrings mapOfLists
      (Left exception) -> Left $ prettyPrintParseException exception
    )
    <$> decodeFileEither file

yamlTest = do
  parsedValue <- readMyType $ "config" </> "example.yaml"
  print parsedValue

运行yamlTest以查看解析结果。