hedn: EDN parsing and encoding

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain]

A EDN parsing and encoding library.

Based on "specs" published at https://github.com/edn-format/edn.


[Skip to ReadMe]

Properties

Versions0.1.3.0, 0.1.4.1, 0.1.5.0, 0.1.5.1, 0.1.5.2, 0.1.6.0, 0.1.7.0, 0.1.8.1, 0.1.8.2, 0.1.9.0, 0.1.9.1, 0.2.0.0, 0.2.0.0, 0.2.0.1
Change logCHANGELOG.md
Dependenciesbase (>=4.9 && <4.13), containers (>=0.5.7 && <0.7), deepseq (>=1.4 && <2), deriving-compat (>=0.3.6 && <0.4), megaparsec (>=7.0 && <8), parser-combinators (>=1.0 && <2), prettyprinter (>=1.2 && <2), scientific (==0.3.*), template-haskell (>=2.11 && <3), text (>=1.2 && <2), time (>=1.6 && <2), uuid (>=1.3 && <2), vector (>=0.11 && <1) [details]
LicenseBSD-3-Clause
Copyright(c) 2019 Alexander Bondarenko
AuthorAlexander Bondarenko
Maintaineraenor.realm@gmail.com
CategoryData
Source repositoryhead: git clone https://gitlab.com/dpwiz/hedn
UploadedFri Jan 18 11:29:49 UTC 2019 by AlexanderBondarenko

Modules

[Index]

Downloads

Maintainers' corner

For package maintainers and hackage trustees


Readme for hedn-0.2.0.0

[back to package description]

Haskell EDN

An EDN parsing and encoding library inspired by aeson.

Based on spec and hints published on GitHub.

Hackage: https://hackage.haskell.org/package/hedn

Stackage: https://www.stackage.org/package/hedn

Examples

AST

(#haskell/edn example/kitchensink ; tagged symbol
 nil ; ugh..
 \space ; character
 "dynamic \"typing\"" ; string
 {:numbers ; keyword
  [42 ; integer
   42.0 ; floating
  ] ; Vector
  :bools
  #{true, false} ; Set (with optional commas)
 } ; Map
) ; List
import qualified Data.EDN as EDN
import qualified Data.Text.IO as Text

main = do
  edn <- Text.readFile "example.edn"
  value <- EDN.parseText "example.edn" edn
  print value
NoTag
  (List
     [ Tagged "haskell" "edn" (Symbol "example" "kitchensink")
     , NoTag Nil
     , NoTag (Character ' ')
     , NoTag (String "dynamic \"typing\"")
     , NoTag
         (Map
            (fromList
               [ ( NoTag (Keyword "bools")
                 , NoTag
                     (Set (fromList [ NoTag (Boolean False) , NoTag (Boolean True) ]))
                 )
               , ( NoTag (Keyword "numbers")
                 , NoTag (Vec [ NoTag (Integer 42) , NoTag (Floating 42.0) ])
                 )
               ]))
     ])

Conversion

More examples in tests/Data/EDN/Class/Test.hs.

data Person = Person
  { personFirst :: Text
  , personLast  :: Text
  } deriving (Eq, Show)

instance ToEDN Person where
  toEDN Person{..} =
    toEDNtagged "myapp" "Person" $ Map.fromList
      [ (EDN.Keyword "first", toEDN personFirst)
      , (EDN.Keyword "last", toEDN personLast)
      ]

instance FromEDN Person where
  parseEDN = \case
    EDN.Tagged "myapp" "Person" v -> Person
      <$> EDN.mapGetKeyword "first" v
      <*> EDN.mapGetKeyword "last" v
    _ ->
      fail "myapp/Person expected"
import qualified Data.EDN as EDN
import qualified Data.Text.IO as Text

main = Text.putStrLn $
  encodeText (Person "Fred" "Mertz")
#myapp/Person {:first "Fred" :last "Mertz"}

Quasiquoter

Embed EDN AST literals with edn:

fredEDN = [edn|
  #myapp/Person {:first "Fred" :last "Mertz"}
|]

Additionally there are QQs for untagged collections. They simply wrap the block in appropriate symbols.

EDN as DSL syntax

You can add quasiquoters for your values by specializing fromEDN QuasiQuoter.

Usual TH shenanigans apply. Define things in a separate module. Either Data.Data.Data or Language.Haskell.TH.Syntax.Lift instance required to convert values to Haskell AST.

module My.Data.QQ (myData) where

import Data.EDN.QQ (fromEDN)
import My.Data.Types (MyData)

myData :: QuasiQuoter
myData = fromEDN @MyData
module Main where

import My.Data.QQ (myData)

main :: IO ()
main = cobc
  [myData|
    {:identification-division
        [#program/id hello]
     :procedure-division
        ((display "Hello, world!"
          end-display)
         stop-run
        )
    }
  |]