Posted by Gizra on Mon, 11/23/2015 - 00:00

planet.elm-lang.org is live!

Nice, right? Planet Elm and its RSS feed is up and running - just grab it, and the best Elm related posts would appear in your favorite RSS reader.

I felt the need for such a site the day I started with Elm. Getting the Gizra devs to build it was the next logical thing.

Having this main site as a central place for aggregating all the interesting content about Elm is yet another step in getting Elm into the mainstream.

If you maintain your own blog, go ahead, and submit your RSS feeds.

Continue reading…

Posted by FRONT END DEV THINGS on Sun, 11/22/2015 - 05:20

Quick follow up to my previous post, this assumes that you have set up your app and dev environment in the way I described.

1. Add a Component directory

mkdir src/Component

2. Create a component

touch src/Component/Hello.elm

3. Edit the component

Notice the magic namespacing here - our module name Component.Hello is derived from the name of the directory and filename.

// src/Component/Hello.elm
module Component.Hello where

import Html exposing (..)

sayHello : String -> Html
sayHello greeting =
div
[ ]
[ text (greeting ++ " from Hello component") ]

4. Import into Main.elm

Note: as Hello is simply an alias to Component.Hello which allows us to call its functions a little more concisely.

// src/Main.elm
module Main where

import Html exposing (..)
import Component.Hello as Hello

main =
Hello.sayHello "uhh... hi"

Posted by FRONT END DEV THINGS on Sun, 11/22/2015 - 02:11

It’s as easy as 1,2,… uhh.. 10

Our goal is to put together an Elm environment that includes custom HTML/SCSS and is suitable for a professional workflow for web applications.

The approach outlined here puts an emphasis on simplicity and minimal dependencies.

View the source code

Features of this environment

  • Customise your index.html (for including css/js etc)
  • Autocompile your Elm code on save (and view errors in IDE)
  • Autocompile your scss
  • Use elm-reactor as a local web server for development

Current limitations

This approach does not yet support use of the elm debugger. If that is unsuitable for you then I encourage you to print this post out and throw it in the trash.

OK, Let’s do this thing.

1. Install Atom IDE

Get the Atom installer here.

I chose Atom over Sublime Text (which is admittedly faster and more stable), Light Table, Microsoft VS Code because it currently has the best Elm language support and is easily extensible.

Maybe I’m backing the wrong horse here but so far Atom is working well for me.

2. Install these Atom packages:

These can also be installed from within Atom via Settings > Install

3. Install Elm on your computer

Get the Elm installer here.

Easy.

4. Create your application directory structure and core files

Type the following into your terminal (using Mac OSX - Windows is very similar. We’re just creating files and folders here)

mkdir MyApp
cd MyApp
mkdir src gen css
touch index.html src/Main.elm css/style.css save-commands.json
elm package install
elm package install evancz/elm-html

5. Configure save-commands to build your Elm files whenever you save them.

The elm make command is the officially supported build tool, so we can just automate that within our IDE instead of using a task runner like Grunt, Gulp, etc.

This part is a little tricky, as at the time of writing there are a couple bugs in this package that throw an error (details below). But it’s ok, we can get through this.

Open up the save-commands.json and enter the following in there.

// save-commands.json
{
"timeout": 5000,
"commands" : [
"src/**/*.elm : elm make src/Main.elm --output=gen/main.js"
]
}

Taking a look at that command in detail… the glob on the left of the colon tells save-commands when you want this command to run. Specifying src/**/*.elm means that it will be run only when we save a file within the src directory, or any of its subdirectories, as long as the file extension is .elm

The command itself is simply the manual elm make command you would use if you weren’t using elm-reactor, targeting only src/Main.elm and outputting it to gen/main.js. The reason we don’t want target all .elm files in the src subdirectory to build is because elm-make is designed to find and compile the necessary dependencies based on the import statements in your code.

Important note: you may get errors on save due to a couple bugs in save-commands. We’re gonna hack this ourselves today, but I expect these will be fixed in the future. Hopefully this will not be necessary in your case.

Commence the Hackery

  1. In Atom, Go to Settings and click the Open Config Folder button
  2. Find save-commands code under packages > save-commands
  3. Line 107 replace .find with .getElementsByClassName
  4. Save and test
  5. If you get an error about div.props not being a function just delete that line we ain’t got time for errors
  6. Be a good citizen and submit a pull request for your well-considered and careful changes.

tl;dr this will compile the Main.elm file (and all imported elm modules) to main.js and it will compile whenever you save any .elm file within src, or any of it’s subdirectories.

6. Set up your styles

This is going to look amazing.

//style.scss
body,
html {
font-family: "Comic Sans MS", cursive;
color: magenta;
}

When you save this file, sass-autocompile will produce a minified css file. Check out the docs to configure this as you like.

7. Set up Main.elm

This will be your app’s entry point.

// src/Main.elm
module Main where

import Html

main =
text "wow"

When you save this file save-commands will run elm-make on it, compiling all your Elm code into into gen/main.js.

8. Set up your html

// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My App</title>
<link rel="stylesheet" href="css/style.min.css">
</head>
<body>
<script src="gen/main.js"></script>
<script>
Elm.fullscreen(Elm.Main);
</script>
</body>
</html>

Your app structure should now look like this:

MyApp
├─ css
│ ├─ style.min.css
│ └─ style.scss
├─ elm-stuff
│ └─ ...
├─ gen
│ └─ main.js
├─ src
│ └─ Main.elm
├─ elm-package.json
├─ index.html
└─ save-commands.json

9. Start your local webserver

Type this in the terminal from your app’s root directory.

elm reactor

10. Gaze upon the glory that is your new application

Point your browser to localhost:8000/index.html

To verify that your Elm code is compiling on save, edit your Main.elm file and hit save.

// src/Main.elm
module Main where

import Html

main =
text "much wow...?"

Refresh your browser (auto-refresh/hot-swap would be nice here instead…) and you should see your changes.

Also notice that since save-commands outputs the results of elm-make in a Elm compiler in an Atom pane you won’t need to keep switching to your terminal or browser to see compiler errors!

Next: organising Elm components

Posted by codecentric on Fri, 11/20/2015 - 16:35

Elm is a functional language, so naturally, functions and function calls are pretty import. We have already seen some functions in the previous episodes. This episode goes into more detail regarding function definition and function application.

About This Series
This is the fifth post in a series of short and sweet blog posts about Elm. The stated goal of this series is to take you from “completely clueless about Elm” to “chief Elm guru”, step by step. If you have missed the previous episodes, you might want to check out the table of contents.
Functions
This is a function definition in Elm:

multiply a b = a * b

The function definition starts with the name of the function, followed by the parameter list. As opposed to C-style languages like Java, JavaScript and the likes, there are no parentheses or commas involved, the parameters are only separated by spaces.
The equals character = separates the function name with the parameter list from the function body. The function body can be any Elm expression that produces a value. We can reference the parameters in the function body.
Function definitions can use other functions in their body. This is how this looks like:

square a = multiply a a

Here, we define a square function by using the multiply function we defined earlier. Function calls also don’t need any parentheses, just list the function parameters you want to pass into the function separated by whitespace.
You do need parentheses when you have nested expresssions:

productOfSquares a b = multiply (square a) (square b)

You can also declare anonymous functions (also known as lambda expressions) on the fly:

incrementAll list = List.map ( n -> n + 1) list

This thing wrapped in ( and ) is an anonymous function that takes one parameter and returns the parameter, incremented by one. This anonymous function is then applied to all elements in a list by using List.map.
Actually, we could have written this shorter. The following is equivalent:

incrementAll2 = List.map ( c -> c + 1)

Why is that the same? Because Elm supports something called currying. incrementAll defines a function that takes a list and produces another list. incrementAll2 also defines a function, but it is a function that takes no arguments and returns another function.
So when we write incrementAll2 [1, 2, 3] Elm first evaluates incrementAll2, gets a function and then procedes to put the remaining arguments ([1, 2, 3] in this case) into this function. The result is the same.
If you find it hard to wrap your head around currying, don’t worry about it too much for now. You can always resort to write a more verbose version of your function without currying and come back to this concept later. As a rule of thumb, if the last element in the parameter list in the function declaration is simply repeated at the end of the function body (like list in this case), you can probably omit both.
Let’s wrap this up. Here is a complete, working Elm program that uses the functions we defined above:

import Html

multiply a b = a * b

square a = multiply a a

productOfSquares a b = multiply (square a) (square b)

incrementAll list = List.map ( c -> c + 1) list

incrementAll2 = List.map ( c -> c + 1)

main = Html.p []
[ Html.text ("3 × 5 = " ++ (toString (multiply 3 5)))
, Html.br [] []
, Html.text ("4² = " ++ (toString (square 4)))
, Html.br [] []
, Html.text ("2² × 3² = " ++ (toString (productOfSquares 2 3)))
, Html.br [] []
, Html.text ("incrementAll [1, 2, 3] = " ++ (toString (incrementAll [1, 2, 3])))
, Html.br [] []
, Html.text ("incrementAll2 [1, 2, 3] = " ++ (toString (incrementAll2 [1, 2, 3])))
]

What happens in these lengthy expressions in the main function? Well, the functions we defined return mostly numbers (or lists, in the case of incrementAll). So we need to convert their results into strings via the toString function (which comes from the Basics package and is imported by default). We then use ++ to append the resulting string to a string literal ("3 × 5 = ", for example) and use Html.text to convert the string into an HTML text node.
Fancy Function Application
Whoa, did you see what we did there to bring the result of one of our functions to the screen? Let’s take a look at Html.text ("3 × 5 = " ++ (toString (multiply 3 5))) for a moment. That’s a lot of parentheses right there. Elm has two operators, |> and <|, to write expressions like that in a more elegant fashion.

  • |>: Take the expression to the left of the operator and put it into the function on the right hand side.
  • <|: Take the expression to the right of the operator and put it into the function on the left hand side.

Here is the main function of the previous program, rewritten with the new operators:
main = Html.p []
[ Html.text <| "3 × 5 = " ++ (toString <| multiply 3 5)
, Html.br [] []
, Html.text <| "4² = " ++ (toString <| square 4)
, Html.br [] []
, Html.text <| "2² × 3² = " ++ (toString <| productOfSquares 2 3)
, Html.br [] []
, Html.text <| "incrementAll [1, 2, 3] = " ++ (toString <| incrementAll [1, 2, 3])
, Html.br [] []
, Html.text <| "incrementAll2 [1, 2, 3] = " ++ (toString <| incrementAll2 [1, 2, 3])
]

If you like to go a bit crazy with this, you can even rewrite

Html.text <| "3 × 5 = " ++ (toString <| multiply 3 5)

as

Html.text <| (++) "3 × 5 = " <| toString <| multiply 3 5

or

square 4 |> toString |> (++) "4² = " |> Html.text

Here we used the infix operator ++ as a non-infix function to be able to apply it with <| and |>. We also used a bit of currying again: (++) actually takes two arguments (the two strings that are to be concatenated). The expression (++) "3 × 5 = " is a partial function application, that is, we provide the first of the two arguments to yield a new function that takes only one argument, prepending "3 × 5 = " to everything that is passed to it.
To read code like this with ease, just imagine this line as the ASCII art represenation of a data pipeline. In |> style pipelines, data flows from left to right, in <| style pipelines, data flows from right to left. So, for example, to decipher a line like Html.text <| (++) "3 × 5 = " <| toString <| multiply 3 5, you start at the end (multiply 3 5), push this into the toString function to convert the number into a string, the resulting string the goes into the append function ((++)) together with the string literal and finally the concatenated string goes into the Html.text function.
This concludes the fifth episode of this blog post series on Elm. Stay tuned for the next episode. See you next Friday!
The post Elm Friday: Functions (Part V) appeared first on codecentric Blog.

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

Now that we have seen the view and the model, it’s time to investigate update; the third and last element of Elm’s Model-Update-View Architecture.

Continue reading…

Posted by codecentric on Fri, 11/13/2015 - 17:30

About This Series
This is the fourth post in a series of short and sweet blog posts about Elm. The stated goal of this series is to take you from “completely clueless about Elm” to “chief Elm guru”, step by step. If you have missed the previous episodes, you might want to check out the table of contents.
Hello World 2.0
This episode builds directly on the previous episode in which we built our first Hello World app in Elm. Printing a simple string is an amazing feat but surely Elm can do a bit more, right? Let’s take a first peek at how Elm works with data structures and renders them to HTML.

The following program sorts a list of names and renders them as an HTML list.

import Html

names = [ "Pearl", "Steven", "Garnet", "Amethyst" ]

main =
let
sorted = List.sort names
texts = List.map Html.text sorted
textToItem text = Html.li [] [ text ]
items = List.map textToItem texts
in
Html.ul [] items

As with every code example, you are encouraged to put this into a file and have a look at the result in the browser by running it with elm-reactor.
This example introduces several new Elm concepts. Let’s go through them one by one:

  • names is defined as a List of strings. Bonus points if get the reference.
  • The main function is the entry point into our program, just as in the Hello World example. It is a bit more involved than the last time, though.
  • The body of the main function is divided into two parts:
    • in the let part we define a bunch of things
    • which are then used in the in part
  • sorted: We use List.sort to sort the list of names in alphabetical order.
  • texts: We use List.map to apply the function Html.text to each element in the list sorted. The result is a list of HTML text elements. (Elm does not render strings to HTML directly, you always have to turn strings into HTML text elements first).
  • textToItem defines a new function on the fly, it takes one HTML text element and wraps it in an HTML li (list item) element, representing an <li> tag.
  • items: We use List.map again to apply our brand new textToItem function to each element in the texts list. The result is a list of HTML li elements.
  • Finally, in the in part of the main function, we wrap the list of li elements in an HTML ul element, rendering them as an <ul> bullet point list.

Attributes
You might have noticed the odd empty list [] literal when we used the Html.li and Html.ul functions. The reason for this is that nearly all functions from the Html module that yield an HTML tag take two arguments: a list of attributes and a list of inner elements. The first argument (the attributes) can be used to set a CSS class, inline styles, event listeners or anything else that is represented as an attribute in HTML. The second argument, the inner element list is the list of HTML elements that will be wrapped in the new HTML element.
Let’s look at this a bit closer. Here is a chunk of Elm that sets some inline styles to center the content on the page and set the font-style:

import Html
import Html.Attributes

names = [ "Pearl", "Steven", "Garnet", "Amethyst" ]

main =
let
sorted = List.sort names
texts = List.map Html.text sorted
textToItem text =
Html.li
[ Html.Attributes.style [("font-style", "italic") ] ]
[ text ]
items = List.map textToItem texts
in
Html.div
[ Html.Attributes.style
[ ("position", "absolute")
, ("width", "10em")
, ("height", "10em")
, ("top", "50%")
, ("left", "50%")
, ("transform", "translateX(-50%) translateY(-50%)")
, ("overflow", "hidden")
]
]
[ Html.ul [] items ]

We have one new import, the module Html.Attributes which bundles all attribute related functions. There are two differences to the previous example here: The li items now have a non-empty list of attributes. We use the function Html.Attributes.style to set their font-style. Also, we wrap the <ul> tag in a div, which also comes with a list of inline styles. Those styles center the div on the page.
We sneakingly introduced a new syntax element here. The style function takes a list of tuples. Tuples are a bit like lists in the very general sense that they represent collections of multiple individual items. There are two important differences: In a list, each element has the same type and lists have a variable length. The elements of a tuple can all have different types and tuples have a fixed length. The number of elements and their individual type is a part of the tuple’s type. Thus, you can’t pass a tuple with three elements (or one) into a function that expects tuples with two elements. In other words, tuples are just pairs (or triplets, quadruplets, …) of values. They are enclosed in ( and ) in Elm.
In this case, each style is a 2-tuple of strings and the argument to style is a list of such tuples.
This concludes the fourth episode of this blog post series on Elm. Stay tuned for the upcoming next episode, where we will have a closer look on types, type inference and type annotations.
The post Elm Friday: Hello World 2.0 (Part IV) appeared first on codecentric Blog.

Posted by codecentric on Fri, 11/13/2015 - 17:29

About This Series
This is the third post in a series of short and sweet blog posts about Elm. The stated goal of this series is to take you from “completely clueless about Elm” to “chief Elm guru”, step by step. If you have missed the previous episodes, you might want to check out the table of contents.

Preparations
Create a new directory, let’s say elm-playground in a convenient location, open a shell and navigate to this directory. Before we can start with the actual Elm code we need to do one little preparation step. Type the following command in your shell:
elm-package install --yes evancz/elm-html
This will install the library to render HTML elements with all its dependencies. If you are familiar with npm install, the elm-package install works in a similar fashion. We will get to Elm’s package system later in this series.
Elm Hello World
Now that this is out of the way, we can write our first app. Honouring the tradition of our craft since the dawn of time (which was 1970-01-01, I think) we start with a Hello World Elm app:
Open your favourite editor and save the following content to a file called HelloWorld.elm in the elm-playground directory:

import Html

main = Html.text "Hello, World!"

Now start elm-reactor in the same directory. This starts a web server which will compile your Elm code on the fly every time it changes.
Open http://localhost:8000/ in a browser. This shows the directory content. Click on the file HelloWorld.elm to see the result of your very first Elm app.
Understanding the Code
Let’s dissect this piece of code and start with the bottom line. Every Elm app needs a main function that serves as the entry point. This function needs to produce some HTML. Our particular main function takes no arguments and produces a constant Html.text element with the given string as its content.
Html.text itself is a function from the module Html, which we imported in the first line. This is a module from the package evancz/elm-html, the one we installed via elm-package install earlier. When calling any function from the Html module (like div, span or text) we need to prefix it with the module name, that is, Html.div, Html.span or, as in this case Html.text. There are ways around this restriction if you prefer brevity over verbosity in your code — we’ll get to that later when we talk about the import statement in detail.
Live Reload
Now change the string “Hello, World!” in your editor to something else, say “Elm rocks!” and save the file. If you reload the page in the browser, elm-reactor will automatically recompile the file and show the new result.
That’s already pretty nice but elm-reactor can do better. Head to http://localhost:8000/ again. This time, instead of clicking on HelloWorld.elm, click the little wrench icon next to it. This opens our app in the debugger. The same can be achieved by appending ?debug to the URL, that is, opening http://localhost:8000/HelloWorld.elm?debug.
Let’s ignore the debug panel on the right for now. Change the text “Elm Rocks!” again and save the file. The Elm debugger will notice the change, recompile and automatically reload the browser without any further action on your side. Pretty neat, huh?
This concludes the third episode of this blog post series on Elm. Make sure to check out the next episode, where we will move past the simple Hello World example and dive a bit deeper into the Elm language.
The post Elm Friday: Hello World (Part III) appeared first on codecentric Blog.

Posted by codecentric on Fri, 11/13/2015 - 17:29

About This Series
This is the second post in a series of short and sweet blog posts about Elm. The stated goal of this series is to take you from “completely clueless about Elm” to “chief Elm guru”, step by step. If you have missed the previous episodes, you might want to check out the table of contents.
Installing Elm
Now that we know what Elm is, we’re all eager to get our hands dirty with it right? There are actually multiple ways to install Elm. There are installers for Windows and Mac available on http://elm-lang.org/install. If you happen to use one of these operating systems, use the installers. You’re a bit out of luck on Linux, since there is no Linux installer. You could build Elm from source, but this would require you to install and set up the Haskell Platform (Elm is build in Haskell) which can be a real pain in the rear. The recommended way to get up and running on Linux is to install Elm via npm:

  • Make sure Node and npm are installed.
  • npm install -g elm
  • That’s it.

Of course this also works on the other platforms.
No matter how you installed Elm, you can (and should) test your Elm installation by typing
elm-make --version
which should produce a response like this:

elm-make 0.2 (Elm Platform 0.15.1)

Usage: elm-make [FILES...] [--output FILE] [--yes] [--report FORMAT] [--warn]
[--docs FILE]
build Elm projects

Available options:
-h,--help Show this help text
--output FILE Write output to FILE.
--yes Reply 'yes' to all automated prompts.
--report FORMAT Format of error and warning reports (e.g.
--report=json)
--warn Report warnings to improve code quality.
--docs FILE Write documentation to FILE as JSON.

To learn more about a particular command run:
elm-make COMMAND --help

This concludes the second episode of this blog post series on Elm. Make sure to check out the next episode, where we finally start to get our hands dirty with some Elm code.
The post Elm Friday: Installing Elm (Part II) appeared first on codecentric Blog.

Posted by codecentric on Fri, 11/13/2015 - 17:28

About This Series
This is the very first post in a series of short and sweet blog posts about Elm. The stated goal of this series is to take you from “completely clueless about Elm” to “chief Elm guru”, step by step. If you already have an idea what Elm is about, you can skip directly to the next episode or check out the table of contents.
So, What Is Elm?
Elm is the next big thing™ for frontends. In an ideal future not too far away, we will do all our frontend work in Elm, so you better hop on the band wagon now. Maybe you have heard about React and Flux and all this stuff the cool kids talk about nowadays? Forget about that. Elm is much better. (Disclaimer: I never did any serious work with React or Flux but I overheard some folks talk about it in the coffee kitchen at the office, so I’m obviously totally qualified to make such a statement.)

Elm is a purely functional, statically typed language that compiles to JavaScript and HTML. It’s syntax is similar to Haskell, so it looks quite different from JavaScript. This might seem a bit scary at first, but rest assured, you’ll get used to it quite quickly.
It comes with some pretty awesome features:

  • Clean, readable, expressive syntax.
  • Type inference.
  • No runtime exceptions. If your Elm code compiles, it will not produce any “undefined is not a function” garbage. Never, ever. Also, when it compiles it usually also does exactly what you intended, right away.
  • It’s reeeeally fast. It claims to be faster than React. But check this benchmark and see for yourself.
  • Powerful but safe interoperability with plain vanilla JavaScript.
  • Great development tools (a live reload server and a time-traveling debugger, among others)

There is one major downside to Elm, though: Once you had a certain amount of Elm exposure and you come back to your old JavaScript (CoffeScript, TypeScript, …) project you’ll long for Elm’s power and clarity and start to ponder how much effort it would be to quickly convert the whole code base to Elm…
You can also check out the official site for more details.
This concludes the first installment of this blog post series on Elm. Now that we know what Elm is, we’re all eager to get going with it, right? Continue with the next episode.
The post Elm Friday: What is Elm? (Part I) appeared first on codecentric Blog.

Posted by codecentric on Fri, 11/13/2015 - 17:27

This is the table of contents for a series of short blog posts about Elm. This blog post has no content of its own, it just links to all blog posts in the series. The table of contents will be updated as the series continues.

Published Episodes

  1. What is Elm?
  2. Installing Elm
  3. Hello World – Your First Elm App
  4. Hello World 2.0 – Render Data Structures to HTML

Upcoming Topics

  • Elm Syntax Basics
  • Tooling Basics (elm-reactor, elm-make)
  • Use multiple modules.
  • Signals
  • The Elm Architecture
  • Using external HTML & CSS
  • Routing
  • JavaScript Interoperability

The post Elm Friday – Table of Contents appeared first on codecentric Blog.

Posted by crossingtheruby.com on Thu, 11/12/2015 - 02:00

Yesterday we built the smallest possible Elm application, consisting only of a view layer. This is one third of the Elm Architecture (Model, Update, View) and today we examine the model.

Continue reading…

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

Inherent in the Elm language are the strict constraints placed on programs by the features immutibility and type inference. These naturally derive what is called The Elm Architecture, consisting of three parts:

Continue reading…

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…