This page is mostly for folks learning Elm. It aggregates questions that are commonly asked on the Slack channel, the IRC channel, or Discourse. Those are all friendly and helpful places to go if you do not find the answer to your question here!

  • Contributions to this document are welcome!

  • This document is about the current version of Elm (0.19 / 0.19.1). See also the Elm 0.17 FAQ about upgrading to Elm 0.17. See the Elm 0.16 FAQ about that older version of Elm.

Contents

What is the difference between type and type alias?

type defines and names a new type (which behaves like an enum with data attached), and type alias gives a name to an existing type.

type alias isn’t creating a distinct type, it is literally just giving a name to an existing type. A type alias will save you keystrokes, but do nothing more. ref

Why does elm repl (or elm make) report “cannot find module ‘Html’”?

You need to install the Html module:

elm install elm/html

Several modules are available by default in the base Elm tools but other common modules like Html have to be installed in the working directory before they can be used in elm make, elm repl, and elm reactor.

How do I know what package name to use for elm install?

Search on package.elm-lang.org for the module name and use the package name that you find there.

How can I write debugging information to the console?

Wrap any value with Debug.log “some message” and that message and the value will be written to the javascript console every time the value is evaluated. For example:

case Debug.log "action" action of

If you want to just log a message and value without using that value, try this in a let clause:

_ = Debug.log "my message" someValue

Also see Debug.todo which gets special treatment from the compiler to provide additional information in the output.

How do I install an older version of Elm, 0.16 for example?

npm install -g elm@0.16

If you need to switch between multiple versions of elm, consider elmenv.

What’s the difference between Html Msg and Html msg?

msg is a placeholder used when the HTML doesn’t send any messages of type Msg (as in type Msg = ...). This is just as a is used as a placeholder in List a when the list is of any type, rather than of strings (List String) or integers (List Int) etc.. msg means “message of any type”.

How can I output literal HTML and avoid escaping of entities?

We used to use the innerHTML property for this, but Elm 0.19 no longer allows that.

See issue #172 for discussion of the issue and possible solutions.

What does () mean?

It is the empty tuple or unit type. It serves much like void, null, or None in other languages.

What good is the <| operator if it is just function application?

It has lower precedence than function application expressed by adjacency (e.g. sqrt x) and is right-associative, and so it can be used instead of parentheses to group function arguments. For example, a b ( c d ) is the same as a b <| c d, and f ( g ( h x ) ) ) can be written as f <| g <| h x. More concretely, max 3 (sqrt x) can be written as max 3 <| sqrt x. 1

Note: The <| operator is essentially the same as $ in Haskell.

What are the Elm operator precedences and associativities?

See an Elm operator precedence table. See also Basics.elm.

How can I use multiple Elm programs on the same page?

You can compile multiple modules into a single elm.js and then instantiate whatever module you need on the appropriate div. 2 For example, bundle multiple main programs (without duplicating any code) into a single elm.js like this:

elm make Header.elm Footer.elm Login.elm --output=elm.js

and then use them like this:

var header = Elm.Header.init({ node: document.getElementById('header') });
var login  = Elm.Footer.init({ node: document.getElementById('login') });
var footer = Elm.Login.init({ node: document.getElementById('footer') });

Use of multiple main modules in one application is discussed here and here.

Does the main module file have to be named “Main.elm”?

No, that is just a convention. Any module that binds main to a value of type Program Never can be an entry point to an Elm program.

For example, if both Foo.elm and Bar.elm contain an appropriate binding of main, compiling via elm make Foo.elm Bar.elm --output=elm.js creates an elm.js file such that both Elm.Foo.init({ node: someElement }) and Elm.Bar.init({ node: someOtherElement }) can be used from the same HTML file.

Why, when I import a module that defines a type, does the compiler know about the type name but not its constructors?

You need to import the module in one of the following ways:

import MyModule exposing (MyType(..)) -- import type and constructors
import MyModule exposing (MyType) -- import only the type, but no constructors.

Similarly, the module itself may export none, or all of a type’s constructors.

module MyModule exposing (MyType(..)) -- exposes all constructors
module MyModule exposing (MyType) -- exposes only MyType, but no constructors.

Just exposing MyType without the (..) will leave the constructors undefined. There are reasons for keeping tags and record constructors secret.

Where can I use type annotations?

In addition to the top-level, type annotations can also be applied to let expressions.

let
  hypotenuse : Float -> Float -> Float
  hypotenuse a b =
    sqrt (a^2 + b^2)
in
  hypotenuse 3 4

How can I join the elmlang.slack.com community?

Sign up at elmlang.herokuapp.com.

How can I recover when elm make fails with errors like “… openFile: does not exist”?

That can happen when switching between elm versions. Try removing all of elm-stuff or just the build-artifacts:

rm -r elm-stuff/build-artifacts

How do I install an Elm package that has not been published to packages.elm-lang.org for use in my project?

Clone the package into a separate directory and add its directory path to the source-directories section of the elm.json file for your project. As usual, you will also have to install any dependencies of the package.

How can I parse Json into Elm data?

Currently you have to write the parsing code. Other than for data passed over ports there is no automatic conversion (and even there, experts recommend writing the parser manually to be able to handle error cases).

How can I pass a record/object over ports?

You have to declare the type of each of its values.

port outgoing : { floatValue : Float, stringValue : String } -> Cmd msg

port incoming : ({ intValue : Int, stringValue : String } -> msg) -> Sub msg

How can I report a compiler error message that could be better?

Report the problem at the error-message-catalog issue tracker with a short, self-contained, correct, example showing both the program and the problematic error messages.

Does Elm have HashMaps?

The core Dict package provides a dictionary mapping unique keys to values. There are some restrictions on key value types; in particular, records cannot be keys.

Why does my app fail immediately with a console error of “Uncaught TypeError: Cannot read property ‘appendChild’ of null”?

Make sure that you are calling Elm’s javascript embed function after the referenced container has been defined in the HTML file.

Similarly, Elm’s fullscreen function should be called only after the page body has started.

Good practice is to call embed or fullscreen at the end of the document body.

How can I load CSS (or other resources) in elm reactor?

It’s not easy. Elm reactor can serve CSS files and so you can write a custom HTML file that links in your CSS and the elm.js generated by Elm and then load that HTML file in elm reactor. But you have to generate the elm.js outside of elm reactor; it is not automatically built or rebuilt on changes to the Elm source.

When you click an Elm source file in elm reactor it compiles just that file (and any dependencies) and sends back the generated javascript which then runs and displays the full page view of the program. So to add any CSS you have to do it in the Elm program itself. Here is an example (thanks to @pdamoc):

import Html exposing (..)
import Html.Attributes exposing (..)

withStyle html =
  div []
  [ node "style" [type_ "text/css"]
    [text "@import url(https://cdnjs.cloudflare.com/ajax/libs/bulma/0.1.2/css/bulma.min.css)"]
  , html
  ]

main =
  div []
    [ a [class "button is-primary"] [text "Primary"]
    , a [class "button is-info"] [text "Info"]
    ]
  |> withStyle

For a more comprehensive solution, see the next question.

How can I integrate Elm development into a larger app with CSS files and other resources?

Elm-reactor is not appropriate for that; it’s geared toward simple pure-Elm applications.

Consider using other hot-reload tools: elm-live, elm-hot-loader, elm-webpack-starter, gulp-elm, or devd.

How does one render an HTML node conditionally?

Use Html.text "" as an empty element. E.g.

if someCondition then
    Html.div [] [ {- ... some substantial Html value here ... -} ]
else
    Html.text ""

Does Elm have ad-hoc polymorphism or typeclasses?

No. Elm provides three super-types that work like typeclasses: number, comparable, and appendable. 3 The Elm language does not allow for defining our own super-types.

The number type comprises Int and Float.

The comparable type comprises Int, Float, Char, String, List, and tuples4.

The appendable type comprises String, List, and text5.

When declaring types the names number, comparable and appendable serve as prefixes. For example, a function declared as

f : number -> number -> String

means that f can take two Int values and return a String, or two Float values and return a String. It cannot take a combination of Int and Float though; the actual types have to be consistent.

However, if declared as

f : number1 -> number2 -> String

then it can also take an Int and a Float and return a String, or take a Float and an Int and return a String. The prefix gives the super-type that constrains the corresponding particular argument. The full super-type name, special prefix plus arbitrary (optional) suffix, determines whether the actual types have to be consistent.

Why doesn’t Elm have user-defined typeclasses?

So far there have not been enough compelling cases to justify adding user-defined typeclasses to the language. See compiler issue #1039.

Which special type variables are there, and how do they work?

There are four special type vairables, which are number, comparable, appendable, and compappend. Please see question Does Elm have ad-hoc polymorphism or typeclasses? for the details.

These built-in type variables work differently from the ones defined by user defined. The main difference is these built-in type variables can only mean what they are defined to mean. For example:

type alias PlusFn t =
  { fn: t -> t -> t
  }

It defines a type alias PlusFn which has one field fn which is a function that accepts two parameters which are of type t, and return a value of the same type. So, we can define any function which take two arguments and return one value, as long as they are of the same type, as the value of the fn field.

> PlusFn (\x y -> x + y)
{ fn = <function> } : Repl.PlusFn number
> PlusFn (\x y -> x ++ y)
{ fn = <function> } : Repl.PlusFn appendable

However, if we change the name t to any built-in type variable, it will work differently. Let’s say we change t to number, then fn must operate on number, i.e. either Int or Float. Since Int and Float don’t support (++) operation, so the following code will not be valid any more:

> PlusFn (\x y -> x ++ y)
-- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm

The argument to function `PlusFn` is causing a mismatch.

4|   PlusFn (\x y -> x ++ y)
             ^^^^^^^^^^^^^^
Function `PlusFn` is expecting the argument to be:

    number -> number -> number

But it is:

    appendable -> appendable -> appendable

How can I change the value of a field in a record?

Strictly speaking, you can’t. Record values (like all Elm values) are immutable. However, you can copy a record value and change one or more of its field values while doing so. Here is an example in elm repl:

> x = { name = "Chris", age = 30 }
{ name = "Chris", age = 30 } : { name : String, age : number }
> y = { x | age = x.age + 1 }
{ name = "Chris", age = 31 } : { name : String, age : number }
> y
{ name = "Chris", age = 31 } : { name : String, age : number }
> x
{ name = "Chris", age = 30 } : { name : String, age : number }

How can I change the value of a nested field?

For example, given model = { foo = { bar = 1 } }, how does one update the value of the bar field? The expression { model | foo.bar = 2 } will not compile.

Here is an expression that returns a copy of model with model.foo.bar updated:

let foo = model.foo in { model | foo = { foo | bar = 2 } }

Or, perhaps more clearly, like this:

let fooBefore = model.foo in { model | foo = { fooBefore | bar = 2 } }

If you need to do this in more than one place, another way is to use a helper function:

{ model | foo = updateHelp model.foo 2 }

updateHelp foo int =
  { foo | bar = int }

How can I pattern match a record and its values at the same time?

You can use a special notation in function definition to pattern match a record and its values at the same time:

changeFooBar ({foo} as model) =
  { model | foo = { foo | bar = 2 } }

See this post

Where are the Cmd and Sub types defined?

They are defined in the core Platform.Cmd and Platform.Sub modules.

What is the difference between Cmd Msg and Cmd msg?

Cmd Msg is a type of command where the resulting messages are of type Msg.

Cmd msg is a more general type of command where the resulting message type is not known. It could just as well be written as Cmd a or Cmd x.

Why does the compiler complain that “You are declaring port `someName` in a normal module.”?

Any module using ports must start with port module on the first line.

How do I generate a new message as a command?

The following function constructs a Cmd value from a message:

message : msg -> Cmd msg
message msg =
    Task.perform identity (Task.succeed msg)

However, this is often unnecessary. To handle a message produced by a call to update you may pass it straight back to update recursively. The package ccapndave/elm-update-extra provides helper functions for implementing this approach elegantly.

The latter approach is likely to be more efficient in most cases. The former option may be attractive when recursive calls to update could cause an infinite loop, or for authors of reusable components interested in creating a clean encapsulation of their library’s internal behavior.

What is the difference between Cmd and Task?

  • Cmd is just a bag (i.e. multiset) of chunks of data. It is a functor, but it is not applicative or monadic. This means all you can do is apply a function to all the entries in the bag with map and add to the bag with batch.

  • Task is a way doing things in sequence. It is monadic, meaning it has an andThen in the API. This means you can say “Do X, and depending on the result, do Y or Z.” From there you can keep chaining things.

The point of this bag of commands is that you can gather all the things that need to happen from your whole app and get them done. The point of a task is to describe a particular thing you want to happen.6

If you need to do any kind of chaining stuff, use Task, and don’t turn your task chain into a Cmd until you have no more chaining stuff to do. This is why APIs generally expose Task instances rather than Cmd: so you can do all the chaining you like, and you’re in charge of finishing the job and turning whatever chain you’ve constructed into a Cmd.7

How do I build an onChange handler for a <select>?

See Building custom DOM event handlers in Elm for some examples of event handlers.

How do I prevent weird DOM behavior (cursor jumps, duplicate input, etc.) for input and textarea fields?

This is a known issue or set of issues, see discussion and workarounds here and here.

How do I navigate to a new route from within a nested view, for example from a page view rather than the top level of my app?

The elm/browser/Browser.Navigation module is the standard for managing browser navigation from within Elm. For changing the URL, you can either use newUrl (which adds to the browser’s history) or replaceUrl (which doesn’t). In either case, you pass it the new URL (String), and get back a Cmd msg.

Typically, on the page where you want to do the navigation (say on clicking a button), you will have

    button [ onClick (NavigateTo Route.SomeRoute) ] [ text "go" ]

and in your update:

   case msg of
       NavigateTo route ->
           ( model,  Browser.Navigation.replaceUrl (Route.routeToString route)  )

where Route.routeToString converts your Route type to a URL (string). This is often moved to a helper function in your Route module:

   case msg of
       NavigateTo route ->
           ( model,  Route.modifyUrl route )

You only need to define a NavigateTo update branch as outlined above, wherever in your app you need to handle browser navigation, and it just works.

Why does this work?

The handling of URL changes within your app is already defined at the top level through Browser.application (which adds an implicit subscription). So replaceUrl and newUrl don’t call a certain message when they are done. It works regardless of the concrete Cmd Msg type of your update, because Cmd msg satisfies any Msg type. (Similar to how you can use generic Html msg in any Html Msg context.)

Here are some more in depth resources on URL parsing and navigation.

There is not one definitive way to do it. Generally, a module in Elm is organized around a data structure relevant to the domain rather than abstracted functions (such as putting all your view or update functions together). See Evan’s recommendations here.

I suspect the heart of a great module in Elm is a data structure. A type or type alias that represents some important and coherent concept. From there, you have functions for working with that data structure. A good test for which functions to include might be to ask: does this function make sense if I only read this module?

For a more detailed approach to code organization for Single Page Applications (SPAs), check out NoRedInk’s style guide.

And for a fully worked example of a simple SPA, see Richard Feldman’s Elm implementation of the “Realworld” app and his tour through it.

What is “elm-community”?

See the Elm-community Manifesto. The elm-community organization came about when some useful packages were no longer being maintained by their creators. The organization formed to make a new home for those packages. Elm-community packages are not inherently more reliable than others but are perhaps more likely to be supported in the long run. Elm-community packages are not a staging area for core.

What does the name “Elm” stand for?

It’s just a name, not an acronym, and it’s not capitalized as “ELM” either. See this elm-discuss message for Evan’s explanation of the name.8

Can I upload a Native module to the package repository?

No, you cannot. The rationale for that policy is explained in this Google groups thread about the Foundation for planning “native” APIs in 0.17 and in this later followup thread about Reframing “native” code as “kernel” code. Those are linked from a Reddit post about An explanation of Elm’s policy on “native code”.

Notes

  1. Function application and the <| operator are discussed at some length here

  2. There is also compappend in the compiler but it does not appear to be exposed for use. 

  3. Tuple comparison is supported only for tuples with 6 or fewer entries. 

  4. The compiler error messages refer to text being appendable; not sure what text means though. [FCY] 

  5. From Evan’s #elm-dev Slack posting, 2016-05-16. 

  6. From rtfeldman’s #elm-dev Slack posting, 2016-05-16. 

  7. But I still think it’s an anagram of Evan’s ML. [FCY]