MyNixOS website logo
Description

Accessible format for structured data serialization.

Serialization of data structures to a Prolog-like Herbrandt-universum-style universal format, useful for type-tagged things and various intermediate representations of program code. The text representation is very simple, allowing interoperability with various minimalistic programming systems.

herb

Herbrandt-universum-style serialization of Haskell values.

  • Like Aeson, but all structures have heads!
  • Like Show, but no precedence issues or ties to Haskell syntax!
  • Like Prolog, but capital case doesn't mean variables!

The grammar is super-simple to allow easy interoperability between programs.

Example

Let's make a small language:

{-# LANGUAGE -XOverloadedStrings #-}
{-# LANGUAGE -XDeriveGeneric #-}
{-# LANGUAGE -XDeriveAnyClass #-}

import Data.Herb
import Data.Herb.Instances

data Expr
  = Number Int
  | Var Ident
  | Apply Expr Expr
  deriving (Show, Generic, FromHerb, ToHerb)

(Some more general typeclasses are provided too, mainly the deriving via wrapper for using Show, auto-deriving from Generic as used above, and HKD support with FromHerb1 and ToHerb1.)

We can convert the data to Herb representation and serialize them:

>>> encodeHerb $ Apply (Var "sqrt") (Number 5)
"Apply(Var(sqrt),Number(5))"

There's a prettyprinter for showing unwieldy values like this symbolic representation of foldr (+) 0 [1..5]:

>>> encodeHerb $ foldr (Apply . Apply (Var "add") . Number) (Number 0) [1..5]
"Apply(Apply(Var(add),Number(1)),Apply(Apply(Var(add),Number(2)),Apply(Apply(Var(add),Number(3)),Apply(Apply(Var(add),Number(4)),Apply(Apply(Var(add),Number(5)),Number(0))))))"

...piping the above through herb-format gives a relatively readable output:

Apply(Apply(Var(add), Number(1)),
      Apply(Apply(Var(add), Number(2)),
            Apply(Apply(Var(add), Number(3)),
                  Apply(Apply(Var(add), Number(4)),
                        Apply(Apply(Var(add), Number(5)), Number(0))))))

There's also an Attoparsec-based parser (the parsers and helper functions are in Data.Herb.Parser):

>>> import Data.Herb.Parser
>>> import Data.Attoparsec.Text
>>> parseOnly herbFile "stuff(this,that) \n stuff(others)"
Right [Struct "stuff" [Atom "this",Atom "that"],Struct "stuff" [Atom "others"]]

...together with a parsing shortcut:

>>> decodeHerb "Apply(Var(sqrt),Number(2))" :: Either String Expr
Right (Apply (Var "sqrt") (Number 2))

And that's it; this isn't supposed to be complex.

Metadata

Version

0.1.0.0

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-freebsd
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64-windows
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows