toml-parser
TOML 1.0.0 parser
| Version on this page: | 1.3.0.0 | 
| LTS Haskell 24.17: | 2.0.1.2@rev:1 | 
| Stackage Nightly 2025-10-31: | 2.0.1.2@rev:1 | 
| Latest on Hackage: | 2.0.1.2@rev:1 | 
toml-parser-1.3.0.0@sha256:ff09ebb6823b965f4ba7ec6923967120332d4832855614d4b8e81b9c1972d525,3065TOML Parser
This package implements a validating parser for TOML 1.0.0.
This package uses an alex-generated lexer and happy-generated parser.
It also provides a pair of classes for serializing into and out of TOML.
Package Structure
---
title: Package Structure
---
stateDiagram-v2
    classDef important font-weight:bold;
    TOML:::important --> ApplicationTypes:::important : decode
    ApplicationTypes --> TOML : encode
    TOML --> [Token]: Toml.Lexer
    [Token] --> [Expr]: Toml.Parser
    [Expr] --> Table : Toml.Semantics
    Table --> ApplicationTypes : Toml.FromValue
    ApplicationTypes --> Table : Toml.ToValue
    Table --> TOML : Toml.Pretty
The highest-level interface to this package is to define FromValue and ToTable
instances for your application-specific datatypes. These can be used with encode
and decode to convert to and from TOML.
For low-level access to the TOML format, the lexer, parser, and validator are available for direct use. The diagram above shows how the different modules enable you to advance through the increasingly high-level TOML representations.
Examples
This file uses markdown-unlit to ensure that its code typechecks and stays in sync with the rest of the package.
import Toml (parse, decode, Value(..))
import Toml.FromValue (FromValue(fromValue), parseTableFromValue, reqKey, optKey)
import Toml.FromValue.Generic (genericParseTable)
import Toml.ToValue (ToValue(toValue), ToTable(toTable), defaultTableToValue)
import Toml.ToValue.Generic (genericToTable)
import GHC.Generics (Generic)
main = pure ()
Using the raw parser
Consider this sample TOML text from the specification.
[[fruits]]
name = "apple"
[fruits.physical]  # subtable
color = "red"
shape = "round"
[[fruits.varieties]]  # nested array of tables
name = "red delicious"
[[fruits.varieties]]
name = "granny smith"
[[fruits]]
name = "banana"
[[fruits.varieties]]
name = "plantain"
Parsing using this package generates the following value
>>> parse fruitStr
Right (fromList [
    ("fruits",Array [
        Table (fromList [
            ("name",String "apple"),
            ("physical",Table (fromList [
                ("color",String "red"),
                ("shape",String "round")])),
            ("varieties",Array [
                Table (fromList [("name",String "red delicious")]),
                Table (fromList [("name",String "granny smith")])])]),
        Table (fromList [
            ("name",String "banana"),
            ("varieties",Array [
                Table (fromList [("name",String "plantain")])])])])])
We can render this parsed value back to TOML text using prettyToml fruitToml.
In this case the input was already sorted, so the generated text will happen
to match almost exactly.
Using decoding classes
Here’s an example of defining datatypes and deserializers for the TOML above.
newtype Fruits = Fruits [Fruit]
    deriving (Eq, Show)
data Fruit = Fruit String (Maybe Physical) [Variety]
    deriving (Eq, Show)
data Physical = Physical String String
    deriving (Eq, Show)
newtype Variety = Variety String
    deriving (Eq, Show)
instance FromValue Fruits where
    fromValue = parseTableFromValue (Fruits <$> reqKey "fruits")
instance FromValue Fruit where
    fromValue = parseTableFromValue (Fruit <$> reqKey "name" <*> optKey "physical" <*> reqKey "varieties")
instance FromValue Physical where
    fromValue = parseTableFromValue (Physical <$> reqKey "color" <*> reqKey "shape")
instance FromValue Variety where
    fromValue = parseTableFromValue (Variety <$> reqKey "name")
We can run this example on the original value to deserialize it into domain-specific datatypes.
>>> decode fruitStr :: Result Fruits
Success [] (Fruits [
    Fruit "apple" (Just (Physical "red" "round")) [Variety "red delicious", Variety "granny smith"],
    Fruit "banana" Nothing [Variety "plantain"]])
Generics
Code for generating and matching tables to records can be derived using GHC.Generics. This will generate tables using the field names as table keys.
data ExampleRecord = ExampleRecord {
  exString :: String,
  exList   :: [Int],
  exOpt    :: Maybe Bool}
  deriving (Show, Generic, Eq)
instance FromValue ExampleRecord where fromValue = parseTableFromValue genericParseTable
instance ToTable   ExampleRecord where toTable   = genericToTable
instance ToValue   ExampleRecord where toValue   = defaultTableToValue
Larger Example
A demonstration of using this package at a more realistic scale can be found in HieDemoSpec.
Changes
Revision history for toml-parser
1.3.0.0 – 2023-07-16
- Make more structured error messages available in the low-level modules.
Consumers of the Tomlmodule can keep getting simple error strings and users interested in structured errors can run the different layers independently to get more detailed error reporting.
- FromValueand- ToValueinstances for:- Ratio,- NonEmpty,- Seq
- Add FromKeyandToKeyfor allowing codecs forMapto use various key types.
1.2.1.0 – 2023-07-12
- Added Toml.Pretty.prettyTomlOrderedto allow user-specified section ordering.
- Added FromValueandToValueinstances forText
- Added reqKeyOfandoptKeyOffor easier custom matching withoutFromValueinstances.
1.2.0.0 – 2023-07-09
- 
Remove FromTableclass. This class existed for things that could be matched specifically from tables, which is what the top-level values always are. HoweverFromValuealready handles this, and both classes can fail, so having the extra level of checking doesn’t avoid failure. It does, however, create a lot of noise generating instances. Note thatToTablecontinues to exist becausetoTableisn’t allowed to fail, and when serializing to TOML syntax you can only serialize top-level tables.
- 
Extracted Toml.FromValue.MatcherandToml.FromValue.ParseTableinto their own modules.
- 
Add pickKey,liftMatcher,inKey,inIndex,parseTableFromValuetoToml.FromValue
- 
Replace genericFromTablewithgenericParseTable. The intended way to derive aFromValueinstance is now to write:instance FromValue T where fromValue = parseTableFromValue genericParseTable
1.1.1.0 – 2023-07-03
- Add support for GHC 8.10.7 and 9.0.2
1.1.0.0 – 2023-07-03
- Add Toml.FromValue.Generic and Toml.ToValue.Generic
- Add Alternative instance to Matcher and support multiple error messages in Result
- Add Data and Generic instances for Value
1.0.1.0 – 2023-07-01
- Add ToTable and ToValue instances for Map
- Refine error messages
- More test coverage
1.0.0.0 – 2023-06-29
- Complete rewrite including 1.0.0 compliance and pretty-printing.
0.1.0.0 – 2017-05-04
- First version.
