Module

Hylograph.Unified

Package
purescript-hylograph-selection
Repository
afcondon/purescript-hylograph-selection

PSD3.Unified - Unified Data DSL for Visualization and Computation

This module re-exports the unified DSL components, providing a single import for the new unified system.

Quick Start

import Hylograph.Unified

-- Define a computation that works in both viz and spreadsheet
growthAnalysis :: forall repr. DataDSL repr => repr (Array Number) -> repr Number
growthAnalysis data_ = avgA (mapA (\x -> x * 1.1) data_)

-- Use Display for formatting
myDisplay :: Display Number String
myDisplay = roundD 2 >>> showNumD >>> suffixD "%"

-- Create attributes with Display
myAttr :: Attribute DataPoint
myAttr = attr "cx" _.x (scaleD 10.0 >>> showNumD)

Module Organization

  • PSD3.Unified.DataDSL - Core type class for data operations
  • PSD3.Unified.Display - Profunctor-based display formatting
  • PSD3.Unified.Attribute - Bridge to PSD3's attribute system
  • PSD3.Unified.Join - Composable join combinators
  • PSD3.Unified.Sugar - Syntactic sugar operators
  • PSD3.Unified.Interpreters.Eval - DataDSL instances for Eval/EvalD

Re-exports from Hylograph.Unified.Attribute

#yD Source

yD :: forall datum. (datum -> Number) -> Display Number String -> Attribute datum

y attribute with display formatting

#xD Source

xD :: forall datum. (datum -> Number) -> Display Number String -> Attribute datum

x attribute with display formatting

#widthD Source

widthD :: forall datum. (datum -> Number) -> Display Number String -> Attribute datum

width attribute with display formatting

#transformD Source

transformD :: forall datum. (datum -> String) -> Attribute datum

transform attribute with display formatting

#toAttribute Source

toAttribute :: forall datum a. AttributeName -> (datum -> a) -> Display a String -> Attribute datum

Convert a Display-based spec to an Attribute

This is useful when you have a Display and want to use it with existing attribute-based code.

#textContentD Source

textContentD :: forall datum a. (datum -> a) -> Display a String -> Attribute datum

text content with display formatting

#strokeD Source

strokeD :: forall datum. (datum -> String) -> Attribute datum

stroke attribute with display formatting

#rD Source

rD :: forall datum. (datum -> Number) -> Display Number String -> Attribute datum

r (radius) attribute with display formatting

#opacityD Source

opacityD :: forall datum. (datum -> Number) -> Attribute datum

opacity attribute with display formatting

#heightD Source

heightD :: forall datum. (datum -> Number) -> Display Number String -> Attribute datum

height attribute with display formatting

#fromDisplay Source

fromDisplay :: forall a. AttributeName -> Display a String -> Attribute a

Create an attribute that just uses a Display for formatting

The extraction is identity - useful when datum is already the right type.

#fillD Source

fillD :: forall datum. (datum -> String) -> Attribute datum

fill attribute with display formatting

#cyD Source

cyD :: forall datum. (datum -> Number) -> Display Number String -> Attribute datum

cy attribute with display formatting

#cxD Source

cxD :: forall datum. (datum -> Number) -> Display Number String -> Attribute datum

cx attribute with display formatting

#attrStatic Source

attrStatic :: forall datum. String -> String -> Attribute datum

Create a static attribute (same for all data)

Example:

attrStatic "fill" "steelblue"
attrStatic "stroke-width" "2"

#attrIndexed Source

attrIndexed :: forall datum a. String -> (datum -> Int -> a) -> Display a String -> Attribute datum

Create an indexed attribute (uses datum and index)

Example:

attrIndexed "fill" (\d i -> if i `mod` 2 == 0 then "red" else "blue") idD

#attr Source

attr :: forall datum a. String -> (datum -> a) -> Display a String -> Attribute datum

Create an attribute from extraction function and display

This is the primary way to create attributes in the new style.

Example:

attr "cx" _.x (scaleD 10.0 >>> showNumD)
attr "fill" _.category idD
attr "opacity" _.importance (clampD 0.0 1.0 >>> showNumD)

Re-exports from Hylograph.Unified.DataDSL

#TypedCell Source

newtype TypedCell :: forall k. k -> Typenewtype TypedCell a

Type-safe cell reference with phantom type tracking the value type

Constructors

#DataSource Source

data DataSource a

Data source - where data enters the computation pipeline

This is the "join point" - analogous to D3's selection.data()

Constructors

#CellAddr Source

type CellAddr = { col :: Int, row :: Int }

Cell address for spreadsheet sources

#DataDSL Source

class DataDSL :: (Type -> Type) -> Constraintclass DataDSL (repr :: Type -> Type)  where

The unified data operations type class

This class captures the fundamental operations on data that are shared between visualization and spreadsheet contexts.

Key insight: These operations are exactly what D3 data joins do, and also what spreadsheet formulas do. They're the same thing!

Members

#TrigDSL Source

class TrigDSL :: (Type -> Type) -> Constraintclass (DataDSL repr) <= TrigDSL repr  where

Trigonometric operations - extension for visualization-specific math

Separated from DataDSL because spreadsheets rarely need trig, but polar/radial visualizations (chord diagrams, pie charts) do.

polarX :: forall repr. DataDSL repr => TrigDSL repr => repr Number -> repr Number -> repr Number
polarX r angle = r `mul` cos angle

Members

#sumA Source

sumA :: forall repr. DataDSL repr => repr (Array Number) -> repr Number

Sum numeric array

Spreadsheet equivalent: =SUM(range)

#productA Source

productA :: forall repr. DataDSL repr => repr (Array Number) -> repr Number

Product of numeric array

Spreadsheet equivalent: =PRODUCT(range)

#negateA Source

negateA :: forall repr. DataDSL repr => repr (Array Number) -> repr (Array Number)

Negate all values in array

Spreadsheet equivalent: =MAP(range, x => -x)

#minA Source

minA :: forall repr. DataDSL repr => repr (Array Number) -> repr Number

Minimum value

Spreadsheet equivalent: =MIN(range)

#maxA Source

maxA :: forall repr. DataDSL repr => repr (Array Number) -> repr Number

Maximum value

Spreadsheet equivalent: =MAX(range)

#countA Source

countA :: forall repr a. DataDSL repr => repr (Array a) -> repr Number

Count elements

Spreadsheet equivalent: =COUNT(range)

#avgA Source

avgA :: forall repr. DataDSL repr => repr (Array Number) -> repr Number

Average of numeric array

Spreadsheet equivalent: =AVERAGE(range)

#absA Source

absA :: forall repr. DataDSL repr => repr Number -> repr Number

Absolute value

Spreadsheet equivalent: =ABS(x)

Re-exports from Hylograph.Unified.Display

#Display Source

newtype Display a b

Display transformation from type a to type b

This is essentially a newtype around a -> b, but with a semantic meaning: it's a non-destructive presentation transformation.

The profunctor structure (contravariant in a, covariant in b) enables flexible composition and adaptation.

Constructors

#yesNoD Source

yesNoD :: Display Boolean String

Boolean display: true -> "Yes", false -> "No"

#upperD Source

upperD :: Display String String

Convert to uppercase

#trimD Source

trimD :: Display String String

Trim whitespace

#thousandsD Source

thousandsD :: Display String String

Add thousands separators: 1234567 -> "1,234,567"

#suffixD Source

suffixD :: String -> Display String String

Add suffix

Example: suffixD "%" makes 50 display as 50%

#signedD Source

signedD :: Display Number String

Signed display: negative in parentheses (accounting style)

Example: -100 -> "(100)", 100 -> "100"

#showNumD Source

showNumD :: Display Number String

Default numeric display (smart formatting)

  • Integers display without decimal point
  • Floats display with minimal precision (trimmed trailing zeros)

#sciD Source

sciD :: Int -> Display Number String

Scientific notation

Example: sciD 2 makes 1234.5 display as 1.23e3

#scaleD Source

scaleD :: Number -> Display Number Number

Scale by a factor

Example: scaleD 100.0 for percentages (0.5 -> 50.0)

#runDisplay Source

runDisplay :: forall a b. Display a b -> a -> b

Run a display transformation

#roundD Source

roundD :: Int -> Display Number Number

Round to N decimal places

Example: roundD 2 makes 3.14159 display as 3.14

#rmapD Source

rmapD :: forall a b b'. (b -> b') -> Display a b -> Display a b'

Covariant map: change output type

Given a way to transform b to b', adapt a Display a b to Display a b'

#prefixD Source

prefixD :: String -> Display String String

Add prefix

Example: prefixD "$" makes 100 display as $100

#percentageD Source

percentageD :: Display Number String

Percentage display: 0.156 -> "15.6%"

#padRightD Source

padRightD :: Int -> Char -> Display String String

Pad right to width with character

#padLeftD Source

padLeftD :: Int -> Char -> Display String String

Pad left to width with character

#lowerD Source

lowerD :: Display String String

Convert to lowercase

#lmapD Source

lmapD :: forall a a' b. (a' -> a) -> Display a b -> Display a' b

Contravariant map: change input type

Given a way to get a from a', adapt a Display a b to Display a' b

Example:

percentageD :: Display Number String
lmapD _.rate percentageD :: Display { rate :: Number } String

#intD Source

intD :: Display Number String

Integer display (truncates decimal part)

#idD Source

idD :: forall a. Display a a

Identity display (does nothing)

#floorD Source

floorD :: Display Number Number

Floor (round down)

#fixedD Source

fixedD :: Int -> Display Number String

Fixed decimal places

Example: fixedD 2 makes 3.1 display as 3.10

#dimapD Source

dimapD :: forall a a' b b'. (a' -> a) -> (b -> b') -> Display a b -> Display a' b'

Profunctor dimap: change both types

#currencyWithSymbol Source

currencyWithSymbol :: String -> Display Number String

Currency with custom symbol

#currencyD Source

currencyD :: Display Number String

Currency display (USD): 1234.56 -> "$1,234.56"

#composeD Source

composeD :: forall a b c. Display a b -> Display b c -> Display a c

Compose two displays (left to right)

f >>> g means: first apply f, then apply g

#compactD Source

compactD :: Display Number String

Compact display for large numbers

Example: 1500000 -> "1.5M", 1500 -> "1.5K"

#clampD Source

clampD :: Number -> Number -> Display Number Number

Clamp to range [lo, hi]

#ceilD Source

ceilD :: Display Number Number

Ceiling (round up)

#boolD Source

boolD :: Display Boolean String

Boolean display: true -> "true", false -> "false"

#absD Source

absD :: Display Number Number

Absolute value

#(>>>) Source

Operator alias for Hylograph.Unified.Display.composeD (left-associative / precedence 9)

Re-exports from Hylograph.Unified.Join

#PhaseSpec Source

type PhaseSpec datum = { attrs :: Array (Attribute datum), transition :: Maybe TransitionConfig }

Configuration for a single GUP phase (enter, update, or exit)

  • attrs: Attributes to apply for this phase
  • transition: Optional animation configuration

#JoinSpec Source

data JoinSpec outer inner

A join specification: data + template + config

The outer/inner type parameters allow type-changing joins. For simple joins where outer = inner, they'll be the same.

Constructors

#JoinConfig Source

type JoinConfig outer inner = { decompose :: Maybe (Decomposer outer inner), gup :: Maybe (GUPSpec inner), key :: String, keyFn :: Maybe (inner -> String), name :: String }

Full join configuration

This captures ALL the information needed to perform any kind of join, with optional decomposition and GUP behaviors.

#JoinBuilder Source

type JoinBuilder outer inner = { data_ :: Array outer, decompose :: Maybe (outer -> Array inner), gup :: Maybe (GUPSpec inner), key :: String, keyFn :: Maybe (inner -> String), name :: String }

Builder type for constructing joins step by step

#GUPSpec Source

type GUPSpec datum = { enter :: Maybe (PhaseSpec datum), exit :: Maybe (PhaseSpec datum), update :: Maybe (PhaseSpec datum) }

Complete GUP specification with all three phases

Each phase is optional - if Nothing, default behavior is used.

#Decomposer Source

type Decomposer outer inner = outer -> Array inner

A decomposer extracts inner data from outer data

Example: _.points :: SceneData -> Array DataPoint

#withGUP Source

withGUP :: forall outer inner. GUPSpec inner -> JoinSpec outer inner -> JoinSpec outer inner

Add GUP (General Update Pattern) behaviors to a join

GUP specifies enter/update/exit behaviors with optional transitions. This replaces UpdateJoin.

join "circles" "circle" circleData $ \d -> ...
  # withGUP
      { enter: Just { attrs: [opacity 0.0], transition: Just fadeIn }
      , update: Just { attrs: [], transition: Just move }
      , exit: Just { attrs: [opacity 0.0], transition: Just fadeOut }
      }

#withDecompose Source

withDecompose :: forall outer inner. (outer -> Array inner) -> JoinSpec outer outer -> JoinSpec outer inner

Add decomposition to a join

Decomposition extracts inner data from outer data, enabling type changes. This replaces NestedJoin.

join "rows" "tr" tableData identity
  # withDecompose (_.cells)  -- Extract cells from each row

Or with type change:

join "circles" "circle" [sceneData] identity
  # withDecompose (_.points)  -- SceneData -> Array DataPoint

#updateSpec Source

updateSpec :: forall datum. Array (Attribute datum) -> Maybe TransitionConfig -> PhaseSpec datum

Create an update phase specification

#toTree Source

toTree :: forall outer inner. JoinSpec outer inner -> Tree outer

Convert a JoinSpec to a Tree (execute the join specification)

This is the final step - it produces the AST node that interpreters (D3, Mermaid, etc.) can process.

myTree :: Tree DataPoint
myTree = join "circles" "circle" dataPoints circleTemplate
  # withGUP myGUP
  # toTree

SAFETY: The unsafeCoerce calls in toTree are safe because:

  1. Type erasure for existentials: PureScript lacks existential types, so we erase the inner datum type when storing decompose/template/gup functions. The functions were provided together at the call site (join/withDecompose/withGUP), guaranteeing they agree on the inner type.

  2. outer = inner when no decompose: Without a decompose function, the join operates on outer directly (JoinSpec outer outer). The coercions are identity in this case.

  3. AST stores erased types: The AST nodes (NestedJoin, UpdateNestedJoin) also use type erasure internally - they recover types via the stored functions at runtime.

#noTransition Source

noTransition :: forall datum. Array (Attribute datum) -> PhaseSpec datum

Phase with no transition (immediate attribute application)

#nestedJoin Source

nestedJoin :: forall outer inner. String -> String -> Array outer -> (outer -> Array inner) -> (inner -> String) -> (inner -> Tree inner) -> JoinSpec outer inner

Nested join with decomposition (equivalent to old NestedJoin)

#join Source

join :: forall datum. String -> String -> Array datum -> (datum -> String) -> (datum -> Tree datum) -> JoinSpec datum datum

Create a basic join specification with key function

This is the foundation - data, a name, keyFn for identity, and a template. Decomposition and GUP can be added with combinators.

The key function extracts identity for matching in updates. This is mandatory because dynamic updates need stable identity matching.

join "nodes" "g" nodeData _.id $ \node ->
  elem Group [...]

#gupJoin Source

gupJoin :: forall datum. String -> String -> Array datum -> (datum -> String) -> (datum -> Tree datum) -> GUPSpec datum -> JoinSpec datum datum

GUP join (equivalent to old UpdateJoin)

#fullJoin Source

fullJoin :: forall outer inner. String -> String -> Array outer -> (outer -> Array inner) -> (inner -> String) -> (inner -> Tree inner) -> GUPSpec inner -> JoinSpec outer inner

Full join with decomposition and GUP (equivalent to old UpdateNestedJoin)

#exitSpec Source

exitSpec :: forall datum. Array (Attribute datum) -> Maybe TransitionConfig -> PhaseSpec datum

Create an exit phase specification

#enterSpec Source

enterSpec :: forall datum. Array (Attribute datum) -> Maybe TransitionConfig -> PhaseSpec datum

Create an enter phase specification

#buildJoin Source

buildJoin :: forall outer inner. JoinBuilder outer inner -> (inner -> Tree inner) -> JoinSpec outer inner

Build a join from a builder spec

This is the low-level API for full control.

#basicJoin Source

basicJoin :: forall datum. String -> String -> Array datum -> (datum -> String) -> (datum -> Tree datum) -> JoinSpec datum datum

Basic join (equivalent to old Join constructor)

Re-exports from Hylograph.Unified.Sugar

#subOp Source

subOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Number

#subLit Source

subLit :: forall repr. DataDSL repr => repr Number -> Number -> repr Number

#strNeqOp Source

strNeqOp :: forall repr. DataDSL repr => repr String -> repr String -> repr Boolean

#strEqOp Source

strEqOp :: forall repr. DataDSL repr => repr String -> repr String -> repr Boolean

#s Source

s :: forall repr. DataDSL repr => String -> repr String

Short alias for str - creates a string literal Usage: s "hello"

#neg Source

neg :: forall repr. DataDSL repr => repr Number -> repr Number

#n Source

n :: forall repr. DataDSL repr => Number -> repr Number

Short alias for num - creates a numeric literal Usage: n 42.0

#mulOp Source

mulOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Number

#mulLit Source

mulLit :: forall repr. DataDSL repr => repr Number -> Number -> repr Number

#lteOp Source

lteOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Boolean

#ltOp Source

ltOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Boolean

#ite Source

ite :: forall repr a. DataDSL repr => repr Boolean -> repr a -> repr a -> repr a

Short alias for ifThenElse - conditional expression Usage: ite (x <. n 0.0) (s "negative") (s "non-negative")

#gteOp Source

gteOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Boolean

#gtOp Source

gtOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Boolean

#eqOp Source

eqOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Boolean

#divOp Source

divOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Number

#divLit Source

divLit :: forall repr. DataDSL repr => repr Number -> Number -> repr Number

#concatOp Source

concatOp :: forall repr. DataDSL repr => repr String -> repr String -> repr String

#b Source

b :: forall repr. DataDSL repr => Boolean -> repr Boolean

Short alias for bool - creates a boolean literal Usage: b true

#addOp Source

addOp :: forall repr. DataDSL repr => repr Number -> repr Number -> repr Number

#addLit Source

addLit :: forall repr. DataDSL repr => repr Number -> Number -> repr Number

#(>=.) Source

Operator alias for Hylograph.Unified.Sugar.gteOp (non-associative / precedence 4)

#(>.) Source

Operator alias for Hylograph.Unified.Sugar.gtOp (non-associative / precedence 4)

#(===) Source

Operator alias for Hylograph.Unified.Sugar.strEqOp (non-associative / precedence 4)

#(==.) Source

Operator alias for Hylograph.Unified.Sugar.eqOp (non-associative / precedence 4)

#(<=.) Source

Operator alias for Hylograph.Unified.Sugar.lteOp (non-associative / precedence 4)

#(<.) Source

Operator alias for Hylograph.Unified.Sugar.ltOp (non-associative / precedence 4)

#(<+>) Source

Operator alias for Hylograph.Unified.Sugar.concatOp (right-associative / precedence 5)

#(/==) Source

Operator alias for Hylograph.Unified.Sugar.strNeqOp (non-associative / precedence 4)

#(/:) Source

Operator alias for Hylograph.Unified.Sugar.divLit (left-associative / precedence 7)

#(/.) Source

Operator alias for Hylograph.Unified.Sugar.divOp (left-associative / precedence 7)

#(-:) Source

Operator alias for Hylograph.Unified.Sugar.subLit (left-associative / precedence 6)

#(-.) Source

Operator alias for Hylograph.Unified.Sugar.subOp (left-associative / precedence 6)

#(+:) Source

Operator alias for Hylograph.Unified.Sugar.addLit (left-associative / precedence 6)

#(+.) Source

Operator alias for Hylograph.Unified.Sugar.addOp (left-associative / precedence 6)

#(*:) Source

Operator alias for Hylograph.Unified.Sugar.mulLit (left-associative / precedence 7)

#(*.) Source

Operator alias for Hylograph.Unified.Sugar.mulOp (left-associative / precedence 7)

Modules
Data.DependencyGraph
Hylograph.AST
Hylograph.Axis.Axis
Hylograph.Brush
Hylograph.Brush.FFI
Hylograph.Brush.Types
Hylograph.Classify
Hylograph.Data.Graph
Hylograph.Data.Graph.Algorithms
Hylograph.Data.Node
Hylograph.Data.Tree
Hylograph.Expr.Animation
Hylograph.Expr.Attr
Hylograph.Expr.Datum
Hylograph.Expr.Expr
Hylograph.Expr.Friendly
Hylograph.Expr.Integration
Hylograph.Expr.Interpreter.CodeGen
Hylograph.Expr.Interpreter.Eval
Hylograph.Expr.Interpreter.Meta
Hylograph.Expr.Interpreter.PureSVG
Hylograph.Expr.Interpreter.SVG
Hylograph.Expr.Path
Hylograph.Expr.Path.Generators
Hylograph.Expr.Sugar
Hylograph.Expr.Units
Hylograph.HATS
Hylograph.HATS.Friendly
Hylograph.HATS.InterpreterTick
Hylograph.HATS.Transitions
Hylograph.Interaction.Brush
Hylograph.Interaction.Coordinated
Hylograph.Interaction.Pointer
Hylograph.Interaction.Zoom
Hylograph.Internal.Attribute
Hylograph.Internal.Behavior.FFI
Hylograph.Internal.Behavior.Types
Hylograph.Internal.Capabilities.Selection
Hylograph.Internal.Capabilities.Transition
Hylograph.Internal.FFI
Hylograph.Internal.Selection.Join
Hylograph.Internal.Selection.Operations
Hylograph.Internal.Selection.Operations.Conversions
Hylograph.Internal.Selection.Operations.Helpers
Hylograph.Internal.Selection.Operations.Selection
Hylograph.Internal.Selection.Query
Hylograph.Internal.Selection.Types
Hylograph.Internal.Transition.FFI
Hylograph.Internal.Transition.Manager
Hylograph.Internal.Transition.Scene
Hylograph.Internal.Transition.Types
Hylograph.Internal.Types
Hylograph.Interpreter.D3
Hylograph.Interpreter.English
Hylograph.Interpreter.Mermaid
Hylograph.Interpreter.MetaAST
Hylograph.Interpreter.SemiQuine
Hylograph.Interpreter.SemiQuine.TreeToCode
Hylograph.Interpreter.SemiQuine.Types
Hylograph.Render
Hylograph.Scale
Hylograph.Scale.FP
Hylograph.Shape.Arc
Hylograph.Shape.Pie
Hylograph.Shape.Polygon
Hylograph.Tooltip
Hylograph.Transform
Hylograph.TreeDSL
Hylograph.TreeDSL.ShapeTree
Hylograph.Unified
Hylograph.Unified.Attribute
Hylograph.Unified.DataDSL
Hylograph.Unified.Display
Hylograph.Unified.Examples
Hylograph.Unified.Join
Hylograph.Unified.Sugar