hydra: Graph programming language

[ apache, data, library, program ] [ Propose Tags ] [ Report a vulnerability ]

Hydra is an implementation of the LambdaGraph data model, which takes advantage of an isomorphism between labeled hypergraphs and typed lambda calculus: in Hydra, "graphs are programs, and programs are graphs". The language is designed to be embedded in other programming languages -- currently Haskell, Java, and Python. Hydra transforms data, schemas, and functional programs into multiple other languages in a way which maintains type safety. It is self-hosting in Haskell -- it generates its own executable source code from Hydra sources -- and it is designed to become self-hosting in its other implementation languages, as well.


[Skip to Readme]

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1.0, 0.1.1, 0.5.0, 0.5.1, 0.8.0, 0.12.0, 0.13.0
Dependencies aeson (>=2.1.0 && <2.3), base (>=4.19.0 && <4.22), base64-bytestring (>=1.2.1 && <1.3), bytestring (>=0.11.5 && <0.13), containers (>=0.6.7 && <0.8), directory (>=1.3.6 && <1.4), filepath (>=1.4.200 && <1.6), hspec (>=2.11.0 && <2.12), HsYAML (>=0.2.1 && <0.3), hydra, scientific (>=0.3.7 && <0.4), split (>=0.2.3 && <0.3), text (>=2.0.2 && <2.2), vector (>=0.12.0 && <0.14) [details]
License Apache-2.0
Author Joshua Shinavier <josh@fortytwo.net>
Maintainer Joshua Shinavier <josh@fortytwo.net>
Uploaded by joshsh at 2026-02-27T23:08:09Z
Category Data
Home page https://github.com/CategoricalData/hydra#readme
Bug tracker https://github.com/CategoricalData/hydra/issues
Source repo head: git clone https://github.com/CategoricalData/hydra
Distributions NixOS:0.12.0
Executables verify-json-kernel, update-kernel-tests, update-json-test, update-json-manifest, update-json-main, update-json-kernel, update-haskell-sources, update-haskell-kernel, update-haskell-eval-lib, update-generation-tests
Downloads 356 total (12 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2026-02-27 [all 1 reports]

Readme for hydra-0.13.0

[back to package description]

Hydra-Haskell

Hydra is a functional programming language based on the LambdaGraph data model, exploring an isomorphism between typed lambda calculus and labeled hypergraphs. See the main Hydra README for project overview and use cases.

This package contains Hydra's Haskell implementation, which serves as the bootstrapping implementation for the entire Hydra project. Releases are available on Hackage.

Code Organization

Hydra-Haskell uses the src/main vs src/gen-main separation pattern (see Code organization wiki page for details).

  • src/main/haskell/ - Hand-written source code

    • Hydra/Dsl/ - DSL syntax definitions
    • Hydra/Sources/ - Kernel specifications written in the DSL
    • Hydra/Lib/ - Native primitive implementations
    • Hydra/Generation.hs - Code generation utilities
  • src/gen-main/haskell/ - Generated code

    • Hydra/Core.hs, Hydra/Graph.hs, etc. - Complete kernel implementation
    • Generated by running writeHaskell in GHCi
  • src/gen-test/haskell/ - Generated test code

    • Kernel tests generated from test sources using writeHaskell
    • Generation tests created using language-specific test generators
    • See Testing section for details

Haskell serves as the bootstrapping implementation - the DSL sources here generate code for Java, Python, and other languages.

Documentation

For comprehensive documentation about Hydra's architecture, type system, and implementation details, see:

  • Concepts - Core concepts: Type, Term, Graph, Flow monad, primitives, coders
  • Implementation - Detailed guide covering type modules, DSLs, primitives, coders, and the bootstrap process
  • DSL Guide - Comprehensive guide to Hydra's domain-specific languages
  • Code Organization - The src/main vs src/gen-main pattern
  • Testing - Common test suite and language-specific testing
  • Developer Recipes - Step-by-step guides for extending Hydra

This README focuses on practical instructions for building, testing, and generating code with Hydra-Haskell.

Build

Haskell is Hydra's bootstrapping language. The entire Hydra kernel is written using Haskell-based domain-specific languages (DSLs):

The DSL sources are also used to generate Java and Python implementations, ensuring parity across each Hydra language variant.

Build and REPL

First, install the Haskell Tool Stack:

# On macOS
brew install haskell-stack

# Other platforms: see https://docs.haskellstack.org/en/stable/install_and_upgrade/

Then build and enter the GHCi REPL:

stack ghci hydra:lib

Note: The hydra:lib target is required to avoid loading test modules. Running stack ghci without a target will load all components including test dependencies, which you may not need.

Test

Run all tests:

stack test

For interactive testing with access to test utilities:

stack ghci hydra:lib hydra:hydra-test

Then in the REPL, you can run individual tests:

Test.Hspec.hspec Hydra.TestSuiteSpec.spec

See the Testing wiki page for details on Hydra's common test suite, which ensures parity across all Hydra language variants.

Code generation

Hydra is self-hosting: it can generate its own source code from DSL definitions.

Generate Haskell code

Enter the GHCi REPL and import the generation module:

import Hydra.Generation

Generate all main modules provided in Hydra-Haskell:

-- First arg: output directory
-- Second arg: universe modules (for dependency resolution)
-- Third arg: modules to generate
writeHaskell "src/gen-main/haskell" mainModules mainModules

Generate only the Hydra kernel (excluding other Hydra-Haskell artifacts like the Haskell coder, the JSON coder, etc.):

writeHaskell "src/gen-main/haskell" kernelModules kernelModules

Generate specific main modules:

-- For specific modules, include dependencies in the universe
writeHaskell "src/gen-main/haskell" mainModules [haskellLanguageModule, haskellCoderModule]

Generate kernel test modules:

let allModules = mainModules ++ testModules
writeHaskell "src/gen-test/haskell" allModules baseTestModules

Or use the convenience script:

./bin/update-kernel-tests.sh

This generates tests that validate the Hydra kernel implementation.

Generate language-specific generation tests (tests that verify code generation to Haskell):

./bin/update-generation-tests.sh

These two types of tests serve different purposes:

  • Kernel tests: Validate core Hydra functionality (type checking, reduction, etc.)
  • Generation tests: Verify that Hydra can correctly generate code in target languages

Note src/gen-test as opposed to src/gen-main.

Generate code for other languages

Java and Python code generation is handled by the Hydra-Ext package. From the hydra-ext directory:

cd ../hydra-ext && stack ghci

Then in GHCi:

import Hydra.Ext.Generation

-- Generate Python kernel
-- Second arg: universe modules (for dependency resolution)
-- Third arg: modules to generate
writePython "../hydra-python/src/gen-main/python" kernelModules kernelModules

-- Generate Java kernel
writeJava "../hydra-java/src/gen-main/java" kernelModules kernelModules

And similar for test artifacts. See the Hydra-Ext README for more details. Hydra-Ext also includes coders for many other languages and formats: Avro, Protobuf, C++, C#, Scala, GraphQL, JSON Schema, RDF, and more.

Working with Hydra

Core types

Some of the fundamental types in Hydra are:

  • Type - Represents the structure of data (literals, records, unions, functions, etc.)
  • Term - Represents data or computation (instances of types)
  • Binding - A named binding (name + term + type scheme), also called an element.
  • Graph - A collection of elements with an environment, types, primitives, and schema graph
  • Module - A namespace containing elements with dependencies on other modules

These are defined in Hydra/Sources/Kernel/Types and code-generated into Hydra.Core, Hydra.Graph, and Hydra.Module.

See Concepts for detailed explanations.

The Flow monad

Transformations in Hydra use the Flow monad for:

  • State management (graph context)
  • Error handling
  • Logging and tracing
type Flow s a = s -> Trace -> FlowState s a

Common usage pattern:

import Hydra.Compute (Flow, FlowState, unFlow, emptyTrace)

-- Create a Flow
myComputation :: Flow Graph String
myComputation = pure "result"

-- Execute it
let state = unFlow myComputation graph emptyTrace
case flowStateValue state of
  Just result -> putStrLn result
  Nothing -> print (flowStateMessages $ flowStateTrace state)

Coders and adapters

Coders are bidirectional transformations:

data Coder s1 s2 v1 v2 = Coder {
  coderEncode :: v1 -> Flow s2 v2,
  coderDecode :: v2 -> Flow s1 v1
}

Adapters also transform types, enabling schema evolution and language mapping.

See the Implementation wiki for details.

DSLs

Hydra provides multiple domain-specific languages for constructing types and terms:

Untyped DSLs (Hydra/Dsl/Types.hs, Hydra/Dsl/Terms.hs):

import qualified Hydra.Dsl.Types as Types
import qualified Hydra.Dsl.Terms as Terms

personType = Types.record [
  "name" >: string,
  "age" >: int32]

alice = Terms.record [
  "name" >: Terms.string "Alice",
  "age" >: Terms.int32 30]

Phantom-typed DSLs (Hydra/Dsl/Meta/Phantoms.hs) - Compile-time type safety:

import Hydra.Dsl.Meta.Phantoms

safeFn :: TTerm (Int -> String)
safeFn = lambda "x" (Strings.toUpper (var "x"))  -- Type-checked at compile time

Library DSLs (Hydra/Dsl/Meta/Lib) - Wrappers for primitive functions:

import Hydra.Dsl.Meta.Lib.Lists as Lists
import Hydra.Dsl.Meta.Lib.Strings as Strings

example = Lists.map (Strings.toUpper) (list ["hello", "world"])

See the DSL system section in the Implementation wiki for comprehensive coverage.

JSON and YAML serialization

Serialize Hydra terms to JSON or YAML:

import Hydra.Kernel
import Hydra.Codegen
import Hydra.Langs.Json.Serde
import Hydra.Dsl.Terms as Terms

-- Get the Hydra core graph
let g = hydraCoreGraph
let flow = fromFlowIo g

-- Define a type
let typ = TypeVariable _Precision

-- Create a term of that type
let term = Terms.inject _Precision (Field _Precision_bits $ Terms.int32 64)

-- Create a JSON coder for the type
coder <- flow $ jsonStringCoder typ

-- Encode to JSON
result <- flow (coderEncode coder term)
putStrLn result

Self-hosting demonstration

Hydra-Haskell is a self-hosting compiler - it can generate its own source code.

Complete self-hosting cycle:

# Generate all kernel code
stack ghci hydra:lib
import Hydra.Sources.All
import Hydra.Generation
writeHaskell "src/gen-main/haskell" mainModules mainModules
:q

# Generate kernel tests
./bin/update-kernel-tests.sh

# Generate language-specific generation tests
./bin/update-generation-tests.sh

# Run all tests
stack test

Alternatively, use GHCi for all generation steps:

stack ghci hydra:lib
import Hydra.Sources.All
import Hydra.Generation
writeHaskell "src/gen-main/haskell" mainModules mainModules
let allModules = mainModules ++ testModules
writeHaskell "src/gen-test/haskell" allModules baseTestModules
:q
stack test

The generated code includes:

  • All core types (Type, Term, Graph, Module, etc.)
  • Type inference and checking
  • Term reduction and rewriting
  • Coders and adapters
  • Primitive functions (signatures only; implementations are in Hydra/Lib)

What remains hand-written:

  • Hydra.Lib - Native primitive implementations
  • Hydra.Sources - DSL-based specifications (input to code generation)
  • Hydra.Dsl - DSL syntax
  • Hydra.Generation - I/O and generation utilities
  • Test runners

See the Bootstrap process section for details on extending Hydra. For example:

Troubleshooting

Stack version warnings

If you see warnings like:

Stack has not been tested with GHC versions above 9.0, and using 9.10.2, this may fail
Stack has not been tested with Cabal versions above 3.4, but version 3.12.1.0 was found, this may fail

Solution: Update Stack to the latest version:

stack upgrade
# or on macOS with Homebrew:
brew upgrade stack

Explanation: These are compatibility warnings that appear when using newer GHC/Cabal versions. If your builds complete successfully, the warnings are harmless - Stack works fine with newer versions even before official testing. Upgrading Stack eliminates the warnings.