-
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
7 changed files
with
173 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
README.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,144 @@ | ||
# tomland | ||
|
||
[](https://hackage.haskell.org/package/tomland) | ||
[](https://travis-ci.org/kowainik/tomland) | ||
[](https://ci.appveyor.com/project/kowainik/tomland) | ||
[](https://hackage.haskell.org/package/tomland) | ||
[](http://stackage.org/lts/package/tomland) | ||
[](http://stackage.org/nightly/package/tomland) | ||
[](https://github.com/kowainik/tomland/blob/master/LICENSE) | ||
|
||
TOML parser | ||
> “A library is like an island in the middle of a vast sea of ignorance, | ||
> particularly if the library is very tall and the surrounding area has been | ||
> flooded.” | ||
> | ||
> ― Lemony Snicket, Horseradish | ||
Bidirectional TOML serialization. The following blog post has more details about | ||
library design: | ||
|
||
* TODO: insert link to blog post | ||
|
||
This README contains a basic usage example of the `tomland` library. All code | ||
below can be compiled and run with the following command: | ||
|
||
``` | ||
cabal new-run readme | ||
``` | ||
|
||
## Preamble: imports and language extensions | ||
|
||
Since this is a literate haskell file, we need to specify all our language | ||
extensions and imports up front. | ||
|
||
```haskell | ||
{-# OPTIONS -Wno-unused-top-binds #-} | ||
|
||
{-# LANGUAGE LambdaCase #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
|
||
import Control.Applicative ((<|>)) | ||
import Control.Category ((>>>)) | ||
import Data.Text (Text) | ||
import Toml (TomlBiMap, TomlCodec, (.=)) | ||
|
||
import qualified Data.Text.IO as TIO | ||
import qualified Toml | ||
``` | ||
|
||
`tomland` is mostly designed for qualified imports and intended to be imported | ||
as follows: | ||
|
||
```haskell ignore | ||
import Toml (TomlCodec, (.=)) -- add 'TomlBiMap' and 'Key' here optionally | ||
import qualified Toml | ||
``` | ||
|
||
## Data type: parsing and printing | ||
|
||
We're going to parse TOML configuration from [`examples/readme.toml`](examples/readme.toml) file. | ||
|
||
This static configuration is captured by the following Haskell data type: | ||
|
||
```haskell | ||
data Settings = Settings | ||
{ settingsPort :: !Port | ||
, settingsDescription :: !Text | ||
, settingsCodes :: [Int] | ||
, settingsMail :: !Mail | ||
, settingsUsers :: ![User] | ||
} | ||
|
||
data Mail = Mail | ||
{ mailHost :: !Host | ||
, mailSendIfInactive :: !Bool | ||
} | ||
|
||
data User | ||
= Admin Integer -- id of admin | ||
| Client Text -- name of the client | ||
deriving (Show) | ||
|
||
newtype Port = Port Int | ||
newtype Host = Host Text | ||
``` | ||
|
||
Using `tomland` library, you can write bidirectional converters for these types | ||
using the following guidelines and helper functions: | ||
|
||
1. If your fields are some simple basic types like `Int` or `Text` you can just | ||
use standard codecs like `Toml.int` and `Toml.text`. | ||
2. If you want to parse `newtype`s, use `Toml.diwrap` to wrap parsers for | ||
underlying `newtype` representation. | ||
3. For parsing nested data types, use `Toml.table`. But this requires to specify | ||
this data type as TOML table in `.toml` file. | ||
4. If you have lists of custom data types, use `Toml.list`. Such lists are | ||
represented as array of tables in TOML. If you have lists of primitive types | ||
like `Int`, `Bool`, `Double`, `Text` or time types, that you can use | ||
`Toml.arrayOf` and parse arrays of values. | ||
5. `tomland` separates conversion between Haskell types and TOML values from | ||
matching values by keys. Converters between types and values have type | ||
`TomlBiMap` and are named with capital letter started with underscore. Main | ||
type for TOML codecs is called `TomlCodec`. To lift `TomlBiMap` to | ||
`TomlCodec` you need to use `Toml.match` function. | ||
|
||
```haskell | ||
settingsCodec :: TomlCodec Settings | ||
settingsCodec = Settings | ||
<$> Toml.diwrap (Toml.int "server.port") .= settingsPort | ||
<*> Toml.text "server.description" .= settingsDescription | ||
<*> Toml.arrayOf Toml._Int "server.codes" .= settingsCodes | ||
<*> Toml.table mailCodec "mail" .= settingsMail | ||
<*> Toml.list userCodec "user" .= settingsUsers | ||
|
||
mailCodec :: TomlCodec Mail | ||
mailCodec = Mail | ||
<$> Toml.diwrap (Toml.text "host") .= mailHost | ||
<*> Toml.bool "send-if-inactive" .= mailSendIfInactive | ||
|
||
_Admin :: TomlBiMap User Integer | ||
_Admin = Toml.prism Admin $ \case | ||
Admin i -> Right i | ||
other -> Toml.wrongConstructor "Admin" other | ||
|
||
_Client :: TomlBiMap User Text | ||
_Client = Toml.prism Client $ \case | ||
Client n -> Right n | ||
other -> Toml.wrongConstructor "Client" other | ||
|
||
userCodec :: TomlCodec User | ||
userCodec = | ||
Toml.match (_Admin >>> Toml._Integer) "id" | ||
<|> Toml.match (_Client >>> Toml._Text) "name" | ||
``` | ||
|
||
And now we're ready to parse our TOML and print the result back to see whether | ||
everything is okay. | ||
|
||
```haskell | ||
main :: IO () | ||
main = do | ||
tomlExample <- TIO.readFile "examples/readme.toml" | ||
let res = Toml.decode settingsCodec tomlExample | ||
case res of | ||
Left err -> print err | ||
Right settings -> TIO.putStrLn $ Toml.encode settingsCodec settings | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
server.port = 8080 | ||
server.codes = [ 5, 10, 42 ] | ||
server.description = """ | ||
This is production server. | ||
Don't touch it! | ||
""" | ||
|
||
[mail] | ||
host = "smtp.gmail.com" | ||
send-if-inactive = false | ||
|
||
[[user]] | ||
id = 42 | ||
|
||
[[user]] | ||
name = "Foo Bar" |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters