Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = System.Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
type bool = System.Boolean
Full name: Microsoft.FSharp.Core.bool
Multiple items
type MeasureAttribute =
inherit Attribute
new : unit -> MeasureAttribute
Full name: Microsoft.FSharp.Core.MeasureAttribute
--------------------
new : unit -> MeasureAttribute
Designing composable functional libraries
not just for visualization
Tomas Petricek
University of Kent and fsharpWorks
tomas@tomasp.net | @tomaspetricek
Motivation
Functional thinking about charts
What is this
talk about?
Making facts great again
Building more open, transparent and engaging data visualization
What is this
talk about?
Functional thinking!
New look at an interesting and tricky domain
What is a chart?
A very long list...
Bar chart
Column chart
Line chart
Area chart
Scatter chart
Histogram
Combo chart???
What is a chart?
Uh...
Maybe chart is just an SVG graphics with text, shapes and pixel coordinates?
What is a chart?
D3 is a too low-level answer
1:
2:
3:
4:
|
x = d3.scaleLinear([0, m - 1], [0, width])
y = d3.scaleLinear([0, 1], [height, 0])
z = d3.interpolateCool
d3.area().x((d, i) => x(i)).y0(d => y(d[0])).y1(d => y(d[1]))
|
Google Charts is a too high-level answer
1:
2:
3:
4:
|
var options = {
vAxis: {title: 'Cups'}, hAxis: {title: 'Month'},
seriesType: 'bars', series: {5: {type: 'line'}} };
chart.draw(data, options);
|
What is a chart?
What is a chart
Fundamentals of a chart
Projections from domain values to pixels
Shapes such as areas and lines
Composition of multiple shapes and text
Interactivity state depends on user input
Composing shapes
Fundamentals of a chart
DEMO
Creating a bar chart
Scales
Continuous and categorical scales
Scales
Continuous and categorical scales
1:
2:
3:
4:
5:
6:
7:
|
type Value =
| Categorical of string * float
| Continuous of float
type Scale =
| Continuous of float * float
| Categorical of string[]
|
Modelling charts
A chart is an algebraic data type
1:
2:
3:
4:
5:
6:
7:
|
type Shape =
| Style of (Style -> Style) * Shape
| Line of seq<Value * Value>
| Shape of seq<Value * Value>
| Axes of (bool * bool * bool * bool) * Shape
| Padding of (float * float * float * float) * Shape
| Layered of seq<Shape>
|
Modelling charts
Avoiding X and Y value mix-up!
1:
2:
3:
4:
5:
6:
7:
|
type Shape<[<Measure>] 'vx, [<Measure>] 'vy> =
| Style of (Style -> Style) * Shape<'vx, 'vy>
| Line of seq<Value<'vx> * Value<'vy>>
| Shape of seq<Value<'vx> * Value<'vy>>
| Axes of (bool * bool * bool * bool) * Shape<'vx, 'vy>
| Padding of (float * float * float * float) * Shape<'vx, 'vy>
| Layered of seq<Shape<'vx, 'vy>>
|
Projections
From domain space to pixel space
1:
|
type Projection<'vx, 'vy, 'ux, 'uy> = (...)
|
1:
2:
3:
4:
5:
|
val project :
Scale<'vx> * Scale<'vy>
-> Value<'vx> * Value<'vy>
-> Projection<'vx, 'vy, 'ux, 'uy>
-> Value<'ux> * Value<'uy>
|
DEMO
Line chart with background
DEMO
Adding a chart title
Composition
There are more ways than one!
1:
2:
3:
4:
5:
|
type Shape<[<Measure>] 'vx, [<Measure>] 'vy> =
| (* ... *)
| InnerScale of Scale<'vx> * Scale<'vy> * Shape<'vx, 'vy>
| OuterScale of Scale<'vx> * Scale<'vy> * Shape<'vx, 'vy>
| Layered of seq<Shape<'vx, 'vy>>
|
Domain modelling
Functional thinking about charts
Domain primitives rather than graphics primitives
Domain values rather than pixels!
Composition in multiple different ways
Units of measure so that I can implement it :-)
Library design
Three functional design patterns
DEMO
Refactoring chart title
Layers of abstraction
From charts to pixels
Transformations
Shape rendering pipeline
DEMO
Creating animated bar chart
State + Update
Elm-based application architecture
Summary
Functional thinking about charts
Composable libraries
Fundamental question
What is the thing we're working with?
Domain modelling
Primitives and composition (with units)
Functional patterns
Multiple layers, transformations, states and updates
Tomas Petricek, University of Kent and fsharpWorks
tomas@tomasp.net | @tomaspetricek