Here is the JavaScript code from part 1 of Mike Bostock's Let's Make a Bar Chart series of tutorials for D3:
var data = [4, 8, 15, 16, 23, 42];
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, 420]);
d3.select(".chart")
.selectAll("div")
.data(data)
.enter().append("div")
.style("width", function(d) { return x(d) + "px"; })
.text(function(d) { return d; });
And here is the PureScript equivalent:
array = [4, 8, 15, 16, 23, 42]
main = do
x <- linearScale
.. domain [0, max id array]
.. range [0, 420]
.. toFunction
rootSelect ".chart"
.. selectAll "div"
.. bindData array
.. enter .. append "div"
.. style' "width" (\d -> show (x d) ++ "px")
.. text' show
Note that ..
is an alias for >>=
. The fluent interface is just a poor man's programmable semicolon!
The PureScript D3 bindings statically enforce several properties of D3's selection semantics; for instance, if you were to remove the .. append "div"
above you would get a type error, because the code following it would be attempting to set things on the unrealized nodes of an enter selection. Similarly, if you removed the .. bindData array
line you would get a type error because you can only obtain an enter selection from an update selection (the selection produced by calling data
in JavaScript or bindData
in PureScript). In JavaScript you would have to wait until runtime to see these kinds of errors.
Selections also carry information about the type of data bound to them (if any). Until data is bound to a selection it is only possible to set constant attributes on it; afterwards you can use well-typed functions of the data.
You can find more examples here.
You will need the following pre-requisites installed:
- PureScript
- nodejs
- bower (e.g.,
npm install -g bower
) - gulp.js (e.g.,
npm install -g gulp
)
Once you have these installed you can run the following in a cloned repo:
npm install # install dependencies from package.json
bower update # install dependencies from bower.json
gulp # compile the code
data D3 :: !
type D3Eff a = forall e. Eff (d3 :: D3 | e) a
data Interpolator :: * -> *
makeInterpolator :: forall a. (a -> a -> Number -> a) -> Interpolator a
class GraphLayout l where
nodes :: forall a. Array a -> l -> D3Eff l
links :: forall a. Array a -> l -> D3Eff l
size :: forall d. { width :: Number, height :: Number | d } -> l -> D3Eff l
data ForceLayout :: *
GraphLayout ForceLayout
forceLayout :: D3Eff ForceLayout
linkDistance :: Number -> ForceLayout -> D3Eff ForceLayout
linkStrength :: Number -> ForceLayout -> D3Eff ForceLayout
friction :: Number -> ForceLayout -> D3Eff ForceLayout
charge :: Number -> ForceLayout -> D3Eff ForceLayout
chargeDistance :: Number -> ForceLayout -> D3Eff ForceLayout
theta :: Number -> ForceLayout -> D3Eff ForceLayout
gravity :: Number -> ForceLayout -> D3Eff ForceLayout
start :: ForceLayout -> D3Eff ForceLayout
alpha :: Number -> ForceLayout -> D3Eff ForceLayout
resume :: ForceLayout -> D3Eff ForceLayout
stop :: ForceLayout -> D3Eff ForceLayout
tick :: ForceLayout -> D3Eff ForceLayout
onTick :: forall e r. (Foreign -> Eff e r) -> ForceLayout -> D3Eff ForceLayout
onDragStart :: forall e r. (Foreign -> Eff e r) -> ForceLayout -> D3Eff ForceLayout
drag :: ForceLayout -> D3Eff ForceLayout
createDrag :: forall s. ForceLayout -> Selection s -> D3Eff (Selection s)
type RequestError = { status :: Number, statusText :: String }
csv :: forall e a. String -> (Either RequestError (Array Foreign) -> Eff (d3 :: D3 | e) a) -> D3Eff Unit
tsv :: forall e a. String -> (Either RequestError (Array Foreign) -> Eff (d3 :: D3 | e) a) -> D3Eff Unit
json :: forall e a. String -> (Either RequestError Foreign -> Eff (d3 :: D3 | e) a) -> D3Eff Unit
class Scale s where
domain :: forall d r. Array d -> s d r -> D3Eff (s d r)
range :: forall d r. Array r -> s d r -> D3Eff (s d r)
copy :: forall d r. s d r -> D3Eff (s d r)
toFunction :: forall d r. s d r -> D3Eff (d -> r)
Scale LinearScale
Scale PowerScale
Scale LogScale
Scale QuantizeScale
Scale QuantileScale
Scale ThresholdScale
Scale OrdinalScale
class Quantitative s where
invert :: s Number Number -> D3Eff (Number -> Number)
rangeRound :: Array Number -> s Number Number -> D3Eff (s Number Number)
interpolate :: forall r. Interpolator r -> s Number r -> D3Eff (s Number r)
clamp :: forall r. Boolean -> s Number r -> D3Eff (s Number r)
nice :: forall r. Maybe Number -> s Number r -> D3Eff (s Number r)
getTicks :: forall r. Maybe Number -> s Number r -> D3Eff (Array Number)
getTickFormat :: forall r. Number -> Maybe String -> s Number r -> D3Eff (Number -> String)
Quantitative LinearScale
Quantitative PowerScale
Quantitative LogScale
data LinearScale :: * -> * -> *
Scale LinearScale
Quantitative LinearScale
data PowerScale :: * -> * -> *
Scale PowerScale
Quantitative PowerScale
data LogScale :: * -> * -> *
Scale LogScale
Quantitative LogScale
data QuantizeScale :: * -> * -> *
Scale QuantizeScale
data QuantileScale :: * -> * -> *
Scale QuantileScale
data ThresholdScale :: * -> * -> *
Scale ThresholdScale
data OrdinalScale :: * -> * -> *
Scale OrdinalScale
linearScale :: forall r. D3Eff (LinearScale Number r)
powerScale :: forall r. D3Eff (PowerScale Number r)
sqrtScale :: forall r. D3Eff (PowerScale Number r)
logScale :: forall r. D3Eff (LogScale Number r)
quantizeScale :: forall r. D3Eff (QuantizeScale Number r)
quantileScale :: forall r. D3Eff (QuantileScale Number r)
thresholdScale :: forall r. D3Eff (ThresholdScale Number r)
ordinalScale :: forall d r. D3Eff (OrdinalScale d r)
exponent :: forall r. Number -> PowerScale Number r -> D3Eff (PowerScale Number r)
base :: forall r. Number -> LogScale Number r -> D3Eff (LogScale Number r)
rangePoints :: forall d. Number -> Number -> Number -> OrdinalScale d Number -> D3Eff (OrdinalScale d Number)
rangeBands :: forall d. Number -> Number -> Number -> Number -> OrdinalScale d Number -> D3Eff (OrdinalScale d Number)
rangeRoundBands :: forall d. Number -> Number -> Number -> Number -> OrdinalScale d Number -> D3Eff (OrdinalScale d Number)
rangeBand :: forall d. OrdinalScale d Number -> D3Eff Number
rangeExtent :: forall d. OrdinalScale d Number -> D3Eff (Tuple Number Number)
data Selection :: * -> *
Appendable Selection
Existing Selection
Clickable (Selection a)
data Update :: * -> *
Appendable Update
Existing Update
data Enter :: * -> *
Appendable Enter
data Transition :: * -> *
Existing Transition
type Exit d = Selection d
data Void
class AttrValue a
AttrValue Number
AttrValue String
rootSelect :: String -> D3Eff (Selection Void)
rootSelectAll :: String -> D3Eff (Selection Void)
select :: forall d. String -> Selection d -> D3Eff (Selection d)
selectAll :: forall d. String -> Selection d -> D3Eff (Selection Void)
bindData :: forall oldData newData. Array newData -> Selection oldData -> D3Eff (Update newData)
enter :: forall d. Update d -> D3Eff (Enter d)
exit :: forall d. Update d -> D3Eff (Exit d)
transition :: forall s d. Existing s => s d -> D3Eff (Transition d)
delay :: forall d. Number -> Transition d -> D3Eff (Transition d)
delay' :: forall d. (d -> Number) -> Transition d -> D3Eff (Transition d)
delay'' :: forall d. (d -> Number -> Number) -> Transition d -> D3Eff (Transition d)
duration :: forall d. Number -> Transition d -> D3Eff (Transition d)
duration' :: forall d. (d -> Number) -> Transition d -> D3Eff (Transition d)
duration'' :: forall d. (d -> Number -> Number) -> Transition d -> D3Eff (Transition d)
class Appendable s where
append :: forall d. String -> s d -> D3Eff (Selection d)
Appendable Selection
Appendable Update
Appendable Enter
class Existing s where
attr :: forall d v. AttrValue v => String -> v -> s d -> D3Eff (s d)
attr' :: forall d v. AttrValue v => String -> (d -> v) -> s d -> D3Eff (s d)
attr'' :: forall d v. AttrValue v => String -> (d -> Number -> v) -> s d -> D3Eff (s d)
style :: forall d. String -> String -> s d -> D3Eff (s d)
style' :: forall d. String -> (d -> String) -> s d -> D3Eff (s d)
style'' :: forall d. String -> (d -> Number -> String) -> s d -> D3Eff (s d)
text :: forall d. String -> s d -> D3Eff (s d)
text' :: forall d. (d -> String) -> s d -> D3Eff (s d)
text'' :: forall d. (d -> Number -> String) -> s d -> D3Eff (s d)
remove :: forall d. s d -> D3Eff Unit
Existing Selection
Existing Update
Existing Transition
class Clickable c where
onClick :: forall eff r. (Foreign -> Eff eff r) -> c -> D3Eff c
onDoubleClick :: forall eff r. (Foreign -> Eff eff r) -> c -> D3Eff c
Clickable (Selection a)
data Axis :: *
axis :: D3Eff Axis
scale :: forall s d. Scale s => s d Number -> Axis -> D3Eff Axis
orient :: String -> Axis -> D3Eff Axis
ticks :: Number -> Axis -> D3Eff Axis
tickFormat :: String -> Axis -> D3Eff Axis
renderAxis :: forall s d. Existing s => Axis -> s d -> D3Eff (Selection d)
data TimeScale :: * -> * -> *
Scale TimeScale
timeScale :: forall r. D3Eff (TimeScale JSDate r)
class Magnitude n
Magnitude Number
Magnitude JSDate
min' :: forall d m. Magnitude m => (d -> m) -> Array d -> m
max' :: forall d m. Magnitude m => (d -> m) -> Array d -> m
min :: forall m. Magnitude m => Array m -> m
max :: forall m. Magnitude m => Array m -> m
extent :: forall m. Magnitude m => Array m -> Array m
extent' :: forall d m. Magnitude m => (d -> m) -> Array d -> Array m
infixl 4 Control.Bind.bind as ..
infixl 4 Data.Function.applyFlipped as ...