Posted by crossingtheruby.com on Tue, 11/10/2015 - 02:00

Tutorials, blog posts and articles are great for getting down to the nitty-gritty but I find conference talks and podcasts a useful way to get a high-level overview. Here are some videos and a couple of podcasts that you should watch, and listen to, to get a taste for Elm.

Continue reading…

Posted by Rundis on Tue, 11/10/2015 - 01:00

After taking a keen interest to Elm lately I figured I needed to solve a real problem. Something a bit fun and achievable in a couple of evenings/nights.
Not being awfully creative, piggiebacking on other peoples' work is sometimes a good option.
In this post I’ll take you through some of my steps in porting/re-implementing https://github.com/cjohansen/react-sweeper (JavaScript and React) to an Elm implementation.

elm sweeper

If you’d like to have a look at the complete implementation of the game, check out https://github.com/rundis/elm-sweeper.
There you’ll find instructions on how to get it running too.

A little background

Right! So I’ve taken an interest in Elm lately. If you’ve read any of my previous posts you might have
noticed that I’m quite fond of Clojure and ClojureScript. I still very much am and I have tons to learn there still. But I wanted to dip my toes
into a statically typed functional language. Elm seems quite approachable and I guess probably the talk "Let’s be mainstream"
made my mind up to give it a go. After creating a language plugin for Light Table: elm-light
and attending an Elm workshop at CodeMesh, I needed something concrete to try it out on.

I remembered that a colleague of mine at Kodemaker, Christian Johansen, made a minesweeper implementation using JavaScript and React.
That seemed like a sufficiently interesting problem and I could shamelessly steal most of the game logic :)

First steps - The Game Logic

So the obvious place to start was the game logic. I had the option of trying to set up Elm-Test
to use a test-driven inspired approach. But heck I figured I had to try to put those types to the test, so I went for
an all out repl driven approach. That gave me a chance to experience the good and bad with the repl integration of my own Light Table Elm plugin too.

elm repl

Starting with records and type aliases

Reading the game logic in react-sweeper I decided to
define a couple of types

type alias Tile (1)
{ id: Int
, threatCount: Maybe Int (2)
, isRevealed: Bool
, isMine: Bool}

type GameStatus = IN_PROGRESS | SAFE | DEAD

type alias Game = (3)
{ status: GameStatus (4)
, rows: Int
, cols: Int
, tiles: List Tile}

1
Type alias for records representing a tile in the game.

2
Threat count is a property on a tile that is not set until the game logic allows it.

3
Type alias for a record representing a game

4
Status of the game, the possible states are defined by GameStatus. SAFE means you’ve won, DEAD…​ well

Describing these types proved to be valuable documentation as well as being very helpful when implementing
the game logic later on.

What’s that Maybe thing ? If someone told me it’s a Monad I wouldn’t be any wiser. I think of it
as a handy way of describing that something may have a value. A nifty way to eliminate the use of null basically.
It also forces you to be explicit about handling the fact that it may not have a value.
You won’t get null pointer errors in an Elm program! (nor Undefined is not a function).

Finding neighbours of a tile

When revealing tiles in minesweeper you also reveal any adjacent tiles that aren’t next to a mine.
In addition you display the threat count (how many mines are adjacent to a tile) for tiles next to those
you just revealed. So we need a way to find the neighbouring tiles of a given tile.

JavaScript implementation

function onWEdge(game, tile) { (1)
return tile % game.get('cols') === 0;
}

function onEEdge(game, tile) { (2)
return tile % game.get('cols') === game.get('cols') - 1;
}

function nw(game, tile) { (3)
return onWEdge(game, tile) ? null : idx(game, tile - game.get('cols') - 1);
}

function n(game, tile) {
return idx(game, tile - game.get('cols'));
}

// etc , ommitted other directions for brevity

const directions = [nw, n, ne, e, se, s, sw, w];

function neighbours(game, tile) {
return keep(directions, function (dir) { (4)
return game.getIn(['tiles', dir(game, tile)]);
});
}

1
Helper function to determine if a given tile is on the west edge of the board

2
Helper function to determine if a given tile is on the east edge of the board

3
Returns the the tile north-west of a given tile. Null if none exists to the north-west

4
Keep is a helper function that maps over the collection and filters out any resulting `null`s. So the function
iterates all directions (invoking their respective function) and returns all possible tiles
neighbouring the given tile.

Elm implementation

type Direction = W | NW | N | NE | E | SE | S | SW (1)

onWEdge : Game -> Tile -> Bool (2)
onWEdge game tile =
(tile.id % game.cols) == 0

onEEdge : Game -> Tile -> Bool
onEEdge game tile =
(tile.id % game.cols) == game.cols - 1

neighbourByDir : Game -> Maybe Tile -> Direction -> Maybe Tile (3)
neighbourByDir game tile dir =
let
tIdx = tileByIdx game (4)
isWOk t = not <| onWEdge game t (5)
isEOk t = not <| onEEdge game t
in
case (tile, dir) of (6)
(Nothing, _) -> Nothing (7)
(Just t, N) -> tIdx <| t.id - game.cols
(Just t, S) -> tIdx <| t.id + game.cols
(Just t, W) -> if isWOk t then tIdx <| t.id - 1 else Nothing
(Just t, NW) -> if isWOk t then tIdx <| t.id - game.cols - 1 else Nothing (8)
(Just t, SW) -> if isWOk t then tIdx <| t.id + game.cols - 1 else Nothing
(Just t, E) -> if isEOk t then tIdx <| t.id + 1 else Nothing
(Just t, NE) -> if isEOk t then tIdx <| t.id - game.cols + 1 else Nothing
(Just t, SE) -> if isEOk t then tIdx <| t.id + game.cols + 1 else Nothing

neighbours : Game -> Maybe Tile -> List Tile
neighbours game tile =
let
n = neighbourByDir game tile (9)
in
List.filterMap identity <| List.map n [W, NW, N, NE, E, SE, S, SW] (10)

1
A type (actually a tagged union) describing/enumerating the possible directions

2
Pretty much the same as it’s JavaScript counterpart. I’ve been lazy and assumed the id of a tile
is also the index in the tiles list of our game.

3
Find a neighbour by a given direction. The function takes 3 arguments; a game record, a tile (that may or may not have a value) and a direction. It returns a tile (that may or may not have a value)

4
tileByIdx is a functions that finds a tile by its index. (it returns a tile, …​ maybe). tIdx is a local function that just curries(/binds/partially applies) the first parameter - game

5
A local function that checks if it’s okay to retrieve a westward tile for a given tile

6
Pattern match on tile and direction. You might consider it a switch statement on steroids.

7
If the tile doesn’t have a value (then we don’t care about the direction hence _) we return Nothing (Maybe.Nothing)

8
Just t, NW matches on a tile that has value (assigned t) and a given direction of NW. The logic is for this case the same as for it’s JavaScript counterpart. Well except it returns Nothing if NW isn’t possible

9
A partially applied version of neightBourByDir to make the mapping function in 10. a bit less verbose

10
We map over all directions finding their neighbours, then List.filterMap identity filters out all List entries with Nothing.
Leaving us with a list of valid neighbours for the given tile.

We covered quite a bit of ground here. I could have implemented all the direction functions as in the JavaScript implementation,
but opted for a more generic function using pattern matching. It’s not that I dislike short functions, quite the contrary but
in this case it felt like a good match (no pun intended). Once you get used to the syntax it gives a
really nice overview as well.

Think of <| as one way to avoid parenthesis. It’s actually a backwards function application

When testing this function I got my first runtime error in Elm complaining that my case wasn’t
exhaustive. Rumors has it that the next version of elm might handle this at compile time as well :-)

elm case error

Threat count

JavaScript

function getMineCount(game, tile) { (1)
var nbs = neighbours(game, tile);
return nbs.filter(prop('isMine')).length;
}

function addThreatCount(game, tile) { (2)
return game.setIn(['tiles', tile, 'threatCount'], getMineCount(game, tile));
}

1
Gets the number of neighbouring tiles that are mines for a given tile. (prop is a helper function for retrieving a named property on a js object)

2
Set the threatCount property on a given tile in the game

Elm

mineCount : Game -> Maybe Tile -> Int (1)
mineCount game tile =
List.length <| List.filter .isMine <| neighbours game tile

revealThreatCount : Game -> Tile -> Tile (2)
revealThreatCount game tile =
{tile | threatCount <- Just (mineCount game <| Just tile)
, isRevealed <- True}

1
Same as for it’s JavaScript counterpart, but using a . syntax for dynamic property access

2
Almoust the same as addThreatCount, but since once we add it the tile would also always be revealed
I opted for a two in one function.

For mine count, both implementations are potentially flawed.

  • For JavaScript you might get 0 for a non-existent tile, which isn’t too bad. But maybe you’ll get
    a null pointer somewhere deeper down the call stack. To be sure you have to crawl through all function calls this function makes and
    apply your JavaScript foo to know things like null < 1 is obviously true, but null < 0 is false. …​ and so on.
  • The elm implementation won’t have any null pointer exceptions, but really it should return Maybe Int to guard
    against giving 0 back for a Nothing tile !

Revealing safe adjacent tiles

JavaScript

function revealAdjacentSafeTiles(game, tile) {
if (isMine(game, tile)) {
return game;
}
game = addThreatCount(game, tile).setIn(['tiles', tile, 'isRevealed'], true);
if (game.getIn(['tiles', tile, 'threatCount']) === 0) {
return keep(directions, function (dir) {
return dir(game, tile);
}).reduce(function (game, pos) {
return !game.getIn(['tiles', pos, 'isRevealed']) ?
revealAdjacentSafeTiles(game, pos) : game;
}, game);
}
return game;
}

Elm

revealAdjacentSafeTiles : Game -> Int -> Game
revealAdjacentSafeTiles game tileId =
case tileByIdx game tileId of
Nothing -> game
Just t ->
if t.isMine then game else
let
updT = revealThreatCount game t
updG = {game | tiles <- updateIn tileId (\_ -> updT) game.tiles}
fn t g = if not t.isRevealed then revealAdjacentSafeTiles g t.id else g
in
if not (updT.threatCount == Just 0) then
updG
else
List.foldl fn updG <| neighbours updG <| Just updT

A brief comparison

The most noteworthy difference is really the explicit handling of an illegal tile index in the Elm implementation.
If I didn’t have the JavaScript code to look at, I’m guessing the difference would have been more noticable. Not necessarily for the better.
We’ll never know.

Anyways, enough about the game logic. Let’s move on to the view part.

Comparing the view rendering

JavaScript

The React part for rendering the UI is found in ui.js
Below I’ve picked out the most interesting parts

export function createUI(channel) { (1)
const Tile = createComponent((tile) => { (2)
if (tile.get('isRevealed')) {
return div({className: 'tile' + (tile.get('isMine') ? ' mine' : '')},
tile.get('threatCount') > 0 ? tile.get('threatCount') : '');
}
return div({
className: 'tile',
onClick: function () {
channel.emit('reveal', tile.get('id')); (3)
}
}, div({className: 'lid'}, ''));
});

const Row = createComponent((tiles) => {
return div({className: 'row'}, tiles.map(Tile).toJS());
});

const Board = createComponent((game) => {
return div({
className: 'board'
}, partition(game.get('cols'), game.get('tiles')).map(Row).toJS());
});

const UndoButton = createComponent(() => { (4)
return button({
onClick: channel.emit.bind(channel, 'undo')
}, 'Undo');
});

const Game = createComponent((game) => {
return div({}, [Board(game), UndoButton()]);
});

return (data, container) => { (5)
render(Game(data), container);
};
}

1
This function returns a function for creating the react component tree for the game. It takes a channel
param, which is an event emitter. So when components need to notify the "controller" about user actions they can just emit messages to this channel
A neat way to avoid using callbacks!

2
createComponent is a handy helper function that avoids some react boiler plate and provides an optimized shouldComponentUpdate function for each react component used.

3
When a user clicks on a tile a reveal message with the tile id is emitted

4
The game also supports undo previous move :)

5
Returns a function that when called starts the react rendering of the game in the given container element

Elm

threatCount : Maybe Int -> List Html
threatCount count =
case count of
Nothing -> []
Just t -> [text (if t > 0 then toString t else "")]

tileView : Signal.Address Action -> Game.Tile -> Html (1)
tileView address tile =
if tile.isRevealed then
div [class ("tile" ++ (if tile.isMine then " mine" else ""))]
<| threatCount tile.threatCount

else
div [class "tile", onClick address (RevealTile tile.id)] (2)
[div [class "lid"] []] (3)

rowView : Signal.Address Action -> List Game.Tile -> Html
rowView address tiles =
div [class "row"] (List.map (tileView address) tiles)

statusView: Game -> Html
statusView game =
let
(status, c) = case game.status of
SAFE -> (" - You won", "status-won")
DEAD -> (" - You lost", "status-lost")
IN_PROGRESS -> ("", "")
in
span [class c] [text status]

view : Signal.Address Action -> Game -> Html (4)
view address game =
let
rows = Utils.partitionByN game.cols game.tiles
in
div [id "main"] [
h1 [] [text "Minesweeper", statusView game],
div [class "board"] (List.map (rowView address) rows),
div [] [button [class "button", onClick address NewGame] [text "New game"]]
]

1
The function responsible for rendering a single tile. Very much comparable to the React tile component
in the JavaScript implementation. Similar to React, we aren’t returning actual dom elments, Elm also has
a virtual dom implementation

2
When a tile is clicked a message is sent to a given address (we’ll get back to that a little bit later).
Well actually it doesn’t happen right away, rather think of it as creating an envelope with content and a known address. The Elm runtime receives a signal back
that will take care of sending the message to it’s rendering function when appropriate.

3
div here is actually a function from the HTML module in Elm. It takes two lists as arguments, the first
is a list of attributes and the second is a list of child elements

4
Our main entry function for creating our view. It takes an address and game as parameter and returns a virtual dom node (Html)

Signal.Address Action : Address points to a particular type of Signal, in our case the Signal is an Action
we’ll come back to that shortly. But the short story is that this is what enables us to talk back to the main application.

Wiring it all together

JavaScript

const channel = new EventEmitter();
const renderMinesweeper = createUI(channel);
let game = createGame({cols: 16, rows: 16, mines: 48});
let history = List([game]);

function render() { (1)
renderMinesweeper(game, document.getElementById('board'));
}

channel.on('undo', () => { (2)
if (history.size > 1) {
history = history.pop();
game = history.last();
render();
}
});

channel.on('reveal', (tile) => { (3)
if (isGameOver(game)) { return; }

const newGame = revealTile(game, tile);

if (newGame !== game) {
history = history.push(newGame);
game = newGame;
}

render();

if (isGameOver(game)) {
// Wait for the final render to complete before alerting the user
setTimeout(() => { alert('GAME OVER!'); }, 50);
}
});

1
The react render entry point for the game. Called whenever the game state is changed

2
The JavaScript implementation keeps a history of all game states. I forgot to mention that immutable-js is for collections.
Undo just gets the previous game state and rerenders. Nice and simple

3
Event listener for reveal messages. It invokes reveal tile, adds to history (and potentially ends the game).

This is all very neat and tidy and works so great because the game state is managed in one place and is passed through
the ui component tree as an immutable value. The fact that the state is immutable also makes the undo implementation a breeze.
I really like this approach !

Elm

If you don’t know Elm at all, this part might be the most tricky to grasp. To simplify things I’ll split it into
two parts.

Start-app approach

Start-app is a small elm package that makes it easy to get started
with an elm Model-View-Update structure. This is a great place to start for your first elm app.

type Action = RevealTile Int (1)

init : Game (2)
init =
Game.createGame 15 15 5787345

update : Action -> Game -> Game (3)
update Action game =
case action of
RevealTile id -> if not (game.status == IN_PROGRESS) then game else (4)
Game.revealTile game id

main = (5)
StartApp.Simple.start (6)
{ model = init
, update = update
, view = view
}

1
Type describing the actions the game supports. Currently just revealing tiles, and you can see that
we also specify that the RevealTile action expects an Int paramater. That would be the tile id.

2
The init function provides the initial state for our application. createGame is a helper function for creating
a game with x cols and y rows. The 3.rd param is a seed for randomizing tiles. We’ll return to that seed thing in the next chapter!

3
Update is the function that handles the actual update of state, or rather the transformation to the next state
based on some action. It’s quite simple in this case, just reveal a given tile and return the updated game

4
No point in revealing more tiles when the game is already over :)

5
main is the entry point into our application. If you use elm-reactor this will be automatically invoked for you, which is handy for getting started quickly

6
StartApp.Simple.start takes care of wiring things up and start your application

Trouble in paradise, we get the same board every time

Do you remember the 3rd param to createGame in the previous chapter? That is the initial seed to a random generator (Random) to randomize the
occurence of mines. The problem is that using the same seed produces the same result. Calling an elm random
generator will return a new seed, so of course I could/should have stored that and used that for the next game.
But I still need an initial seed that’s different every time I start the app. Current time would be a good candidate
for an initial seed. But there is no getCurrentTime function in Elm. Why ? It’s impure, and Elm doesn’t like impure functions.
By "pure", we mean that if you call a function with the same arguments, you get the same result.
There are several reasons why pure functions is a great thing (testing is one), but I won’t go into that, let’s just accept the fact
that this is the case, so how can we deal with it ?

Well the elm-core package has a Time module with a timestamp function that looks useful.
To use that we have to change a few things though, most notably we can’t use the simple start app approach any more.

type Action =
NewGame (1)
| RevealTile Int

update : (Float, Action) -> Game -> Game (2)
update (time, action) game =
case action of
NewGame -> Game.createGame 15 15 (truncate time) (3)
RevealTile id -> if not (game.status == IN_PROGRESS) then game else
Game.revealTile game id

actions: Signal.Mailbox Action (4)
actions =
Signal.mailbox NewGame

model: Signal Game (5)
model =
Signal.foldp update init (Time.timestamp actions.signal)

main : Signal Html (6)
main =
Signal.map (view actions.address) model

port initGame : Task.Task x () (7)
port initGame =
Signal.send actions.address NewGame

1
We introduce a new action NewGame

2
Our update function now takes a tuple of time and action + game as input parameters

3
We use the elm core function truncate to convert the time(stamp) float into an integer and use that as our seed to createGame

4
We construct a mailbox for our Action messages manually, with an initial value of NewGame

5
Our model is a fold (reduce) of all state changes sent to our mailbox (from the app started to the current moment of time).
This is where we introduce the Time.timestamp function, which wraps our action signal and produces a tuple of (timestamp, action)

6
main is just a map over our view function with our current model. Since view also expects an (mailbox) address we curry/partially apply that to our view function

7
Unfortunately I couldn’t figure out how to get the timestamp passed to the init function. The creation
step (4) of the mailbox doesn’t actually cause the NewGame action to be executed either. So this is a little hack
that fires off a task to execute the NewGame action. This is run after initialization so when you load the game you’ll not see state 0 for the game, but actually state 1.
If any elm-ers out there reads this, feel free to comment on how this could be done in a more idiomatic fashion!

I found this blogpost
very illuminating for deconstructing start-app.

But what about undo ?

There is an elm-package I think would help us do that quite simply;
elm-undo-redo. However if you are using elm-reactor
you pretty much get undo-redo and more out of the box. Great for development, but maybe not so much for production!

Summary

Getting into Elm has been a really pleasurable experience so far. It’s quite easy to get up and running without
knowing all that much about the language. I’ve found the elm compiler to be a really nice and friendly companion.
The error messages I get are really impressive and I can truly say I’ve never experienced anything quite like it.
Working with types (at least for this simple application) hasn’t felt like a burden at all. I still feel I should have
had some tests, but I think I would feel more comfortable refactoring this app with a lot less tests than I would in say JavaScript.

If my intention for this post had been to bash JavaScript I chose a poor example to compare with. But then again
that was never my intention. I wanted to show how a well written JavaScript app might compare to an Elm implementation
written by an Elm noob. Hopefully I’ve also managed to demonstrate that it’s not all that difficult getting started with Elm and perhaps
peeked your interest enough to give it a try !

Resources

These are some of the resources that have helped me getting up to speed:

Addendum - Potential improvements

  • Initialize game with seed without adding an extra state
  • Perhaps I should/could have used extensible records to model the game
  • Maybe Array would be a better choice than List for holding tiles ?
Posted by crossingtheruby.com on Mon, 11/09/2015 - 02:00

A friend asked me to elaborate on why I hadn’t included ClojureScript alongside CoffeeScript and TypeScript in a previous post, and why I alluded to the significance of the fact that Elm was Elm and not ElmScript. The omission was deliberate and my thoughts on ‘Script’ are speculative but my answers to both questions are inter-related and hopefully by going into detail you’ll be able to see what I was getting at.

Continue reading…

Posted by crossingtheruby.com on Sun, 11/08/2015 - 02:00

I was fortunate to book a seat to the Elm Tutorial at the CodeMesh conference in London with Elm author Evan Czaplicki at the very last minute. Fortunate because there was space left but also because if I hadn’t left it to the last responsible moment then I would likely have booked a flight in from Amsterdam instead of the train through the channel tunnel. As it happened, thick fog had grounded most planes at Schiphol on Monday morning so the only downside to the train was that I was forced to purchase a seat in first class.

Continue reading…

Posted by crossingtheruby.com on Sat, 11/07/2015 - 02:00

It didn’t take long for Elm to grab my attention. While keeping abreast of developments in the React.js world I was listening to the JavaScript Jabber podcast, episode 179 with Dan Abramov, off the back of his React Europe talk ‘Live React: Hot Reloading with Time Travel’. He was talking about the Redux architecture applied to React and the many benefits that came out of structuring applications in that way. He also mentioned being called out by Evan Czaplicki for not crediting or referencing Elm in that talk as much as he might have done due to the similarity of Redux to Elm and the Elm Architecture. Dan went on to say:

Continue reading…

Posted by crossingtheruby.com on Fri, 11/06/2015 - 02:00

I have never been quite as excited about a programming language as I am about Elm. It’s been only two weeks since I first set eyes on it, yet I am completely and utterly sold. The last time I had a comparable experience was when Ruby with Rails convinced me, by their elegance and fitness for purpose, that I should in fact learn to program and make a career out of it.

Continue reading…

Posted by Gizra on Thu, 11/05/2015 - 00:00

As part of our adoption of Elm in production, Gizra devs are learning and practicing their Elm skills.

After they are done going over the existing videos/tutorials, we let them get their hands dirty. elm-hedley was created just for that - to simulate a simple yet typical web app with login, RESTful, etc.

Here's the existing app. As you see each event appears as a clickable link.

The challenge is to add a counter next to each event label that increments when clicked. When you refresh the page (F5) it shouldn't remember the previous clicks and should start back at 0.

In short, it should look like this (notice the bottom left list):

Go ahead, fork the repo and try for yourself. And don't peek below, as it has the answer!

.
.
.
.
.

Continue reading…

Posted by Rundis on Fri, 10/30/2015 - 01:00

Background

I’ve just started playing around a little bit with elm.
This weekend I’m going to codemesh where I’ll be attending an Elm workshop
with the author of Elm, Evan Czaplicki.

To ensure I have an editor I’m familiar with and to get me started a little, I figured I’d create an Elm language plugin
for Light Table. However lately I’ve been a little busy helping out getting https://github.com/LightTable/LightTable version 0.8
released. Last weekend we got an 0.8 alpha out. I needed some of the features from Electron. So now with Light Table using
Electron under the hoods I could finally complete an intial plugin release. It’s rough, but it’s an ok start I suppose !

Demo

ScreenCast demo

The plugin

You can find the plugin repo on github https://github.com/rundis/elm-light

Posted by theburningmonk.com on Mon, 10/26/2015 - 09:00

Tweet Series: Algae Pythago­ras Tree Can­tor Dust Koch Curve Sier­pin­ski Triangle Dragon Curve Frac­tal Plant (this) Last time out we imple­mented the Dragon Curve exam­ple from the L-System wikipedia page. Now, we’re finally at the end of our journey, let’s see how we can implement the Fractal Plant example in Elm.   Example 7 :

Posted by theburningmonk.com on Thu, 10/22/2015 - 10:00

Tweet Series: Algae Pythago­ras Tree Can­tor Dust Koch Curve Sier­pin­ski Triangle Dragon Curve (this) Frac­tal Plant Last time out we imple­mented the Sierpinski Triangle exam­ple from the L-System wikipedia page. Now, let’s con­tinue our jour­ney and see how we can imple­ment the (rather impressive sounding) Dragon Curve exam­ple in Elm.   Example 6 : Dragon

Posted by Gizra on Thu, 10/22/2015 - 00:00

In my last post I was giving a high level overview of why we were looking at Elm in Gizra. Since that post, we've almost completed the demo app, and we've changed our status from "Looking at Elm" to "Choosing Elm".

The reason? In short - I believe it will save us money.
(Oh, and it's fun)

Continue reading…

Posted by theburningmonk.com on Mon, 10/19/2015 - 10:00

Tweet Series: Algae Pythago­ras Tree Can­tor Dust Koch Curve Sier­pin­ski Triangle (this) Dragon Curve Frac­tal Plant Last time out we imple­mented the Koch Curve exam­ple from the L-System wikipedia page. Now, let’s con­tinue our jour­ney and see how we can imple­ment the Sierpinski Triangle exam­ple in Elm.   Example 5 : Sierpinski Triangle First, let’s

Posted by theburningmonk.com on Thu, 10/15/2015 - 10:00

Tweet Series: Algae Pythago­ras Tree Can­tor Dust Koch Curve (this) Sier­pin­ski Triangle Dragon Curve Frac­tal Plant Last time out we imple­mented the Cantor Dust exam­ple from the L-System wikipedia page. Now, let’s con­tinue our jour­ney and see how we can imple­ment the Koch Curve exam­ple in Elm.   Example 4 : Koch Curve Once again,

Posted by theburningmonk.com on Mon, 10/12/2015 - 10:00

Tweet Series: Algae Pythagoras Tree Cantor Dust (this) Koch Curve Sierpinski Triangle Dragon Curve Fractal Plant Last time out we implemented the Pythagoras Tree example from the L-System wikipedia page. Now, let’s continue our journey and see how we can implement the Cantor Dust example in Elm. Example 3 : Cantor Dust First, let’s define

Posted by Gizra on Thu, 10/01/2015 - 00:00

Part of my job is to get my hands dirty with technologies I stumble upon. I've decided to have a go at React. Well, one thing led to the other and it seems I went down the client side rabbit hole. I'd like to share with you my path - watch out though, it's a slippery slope.


"Hello World" in Elm

It all started with this Thinking Flux video which explains the problems Facebook faced in its front-end and the new application architecture they are now using.

Since the Flux concept was out, different libraries were written implementing it, but in my view it seems that Redux is the winner in terms of simplicity, popularity, docs and community. I really recommend going over it - at least the intro and basics. You might be tempted to actually learn a bit of React (tutorial) to follow the examples more easily.

Then I saw Redux was crediting Elm for some of its inspiration, so I decided to give it a quick look. I was immediately blown away by Elm. The syntax is weird (unless you know Haskell), it has a crazy learning curve, but a lot of it makes so much sense.

The following recording is a presentation I first gave internally for Gizra devs, then as a BoF in DrupalCon Barcelona, and finally recorded to share it with everyone.

My goal is to get more people excited about Elm so the community and contributions grows. I feel it is now very much like Drupal about 10 years ago - a small community, far from being mainstream, but with a lot of potential.

Maybe if we'll draw from Drupal's experience in building and cultivating a community we'll be able to bring this awesome tool closer to the mainstream.

Continue reading…