├── .gitignore ├── .travis.yml ├── 16.md ├── 17-tasks.md ├── 17.md ├── CNAME ├── Gemfile ├── Makefile ├── README.md ├── _config.yml ├── _includes ├── footer.html ├── head.html └── header.html ├── _layouts ├── default.html ├── page.html └── post.html ├── _sass ├── _base.scss ├── _custom.scss ├── _layout.scss └── _syntax-highlighting.scss ├── assets ├── anchor.min.js ├── elm.js ├── filter.js └── tangram-runner.png ├── css └── main.scss ├── favicon.ico ├── index.md └── operators.html /.gitignore: -------------------------------------------------------------------------------- 1 | .jekyll-metadata 2 | .sass-cache 3 | _site 4 | Gemfile.lock 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.3 4 | script: "bundle exec jekyll build" 5 | -------------------------------------------------------------------------------- /16.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Elm 0.16 3 | layout: page 4 | --- 5 | 6 | **Warning: This page concerns Elm version 0.16.** 7 | The information here is no longer correct for the current version of Elm. 8 | 9 | For general questions about the current version see the [main FAQ page](index.html). 10 | 11 | #### Contents 12 | 13 |
14 | 15 | 16 | ### Why does elm-repl (or elm-make) report "cannot find module 'Html'"? 17 | You need to install the Html module: 18 | 19 | elm package install evancz/elm-html 20 | 21 | Several modules are [available by default](http://package.elm-lang.org/packages/elm-lang/core/latest) 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. 22 | 23 | 24 | ### How do I generate an Action as an Effect? 25 | 26 | Effects.task (Task.succeed SomeAction) 27 | 28 | 29 | ### Why isn't my StartApp-based program running any tasks? 30 | 31 | You need to set `app.port`. 32 | 33 | ```haskell 34 | port tasks : Signal (Task.Task Never ()) 35 | port tasks = 36 | app.tasks 37 | ``` 38 | 39 | 40 | ### Why doesn't the `<~` operator work? 41 | 42 | It was removed in Elm version 0.16. You can still get it (or the equivalent `andMap`) from 43 | [Signal.Extra](http://package.elm-lang.org/packages/Apanatshka/elm-signal-extra/latest/Signal-Extra) 44 | instead. 45 | 46 | 47 | ### Why doesn't my application get the initial value of Window.dimensions? 48 | 49 | For example, given this: 50 | 51 | ```haskell 52 | modelInit = { window = (-1,-1) } 53 | 54 | main = Signal.map Element.show model 55 | 56 | model = Signal.foldp (\d s -> {s | window = d}) modelInit Window.dimensions 57 | ``` 58 | 59 | the displayed value will remain at "{ window = (-1,-1) }" until the window is resized, at which time the display tracks all changes. 60 | 61 | This arises because `Signal.foldp` does not use the initial value of its input signal (`Window.dimensions` in this case). 62 | 63 | One solution is to use the `foldp'` function from the Apanatshka/elm-signal-extra package, as follows: 64 | 65 | ```haskell 66 | model = Signal.Extra.foldp' (\d s -> {s | window = d}) (\d -> { window = d }) Window.dimensions 67 | ``` 68 | 69 | Whereas `foldp` takes an initial value parameter, `foldp'` takes instead a function from the initial value of the input signal to the initial value returned by `foldp'`. 70 | 71 | Since StartApp uses `foldp` this problem with initial values can arise when it is used. Also, the problem is not specific to Window.dimensions; it can arise for any input signal whose initial value is of interest. 72 | 73 | 74 | 75 | ### Why is my app failing immediately saying "Cannot read property 'make' of undefined"? 76 | 77 | That can happen if you write custom Javascript code to call `Elm.embed()` or `Elm.fullscreen()` and the application name used there (the first parameter) does not match the main module name. 78 | 79 | For example, if Foo.elm contains the `main` function for your app then your Javascript code should call it like this: 80 | 81 | ```javascript 82 | app = Elm.embed(Elm.Foo, ...) 83 | ``` 84 | 85 | If you use a name other than `Elm.Foo` there you will likely get that "Cannot read property" error. 86 | -------------------------------------------------------------------------------- /17-tasks.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Elm 0.17 Tasks 3 | layout: page 4 | --- 5 | 6 | Here are some ways to convert Elm 0.16 code that uses `Effects.task` into Elm 0.17. 7 | 8 | The cases are sorted by priority, so use the first one that applies to your code. 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Elm 0.16 exampleElm 0.17 equivalent
task |> Task.toMaybe |> Effects.tasktask |> Task.perform (always Nothing) Just
task |> Task.toResult |> Effects.tasktask |> Task.perform Err Ok
task |> Task.map action |> Effects.tasktask |> Task.Extra.performFailproof action
task |> Effects.tasktask |> Task.Extra.performFailproof identity
32 | 33 | 34 | The function `performFailproof` used in two places above is from package [NoRedInk/elm-task-extra](http://package.elm-lang.org/packages/NoRedInk/elm-task-extra). 35 | 36 | This recommendation comes from an 37 | [elm-discuss posting](https://groups.google.com/d/msg/elm-discuss/gkdCrioDsUQ/cJn5-n6fFQAJ) 38 | by Janis Voigtländer on 2016-05-19. 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /17.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Elm 0.17 3 | layout: page 4 | --- 5 | This page concerns questions that arose with Elm version 0.17. 6 | 7 | For general questions see the [main FAQ page](index.html). 8 | 9 | #### Contents 10 | 11 |
12 | 13 | 14 | ### Where are the official documents about Elm version 0.17? 15 | 16 | * [A Farewell to FRP][farewell]: Evan's blog announcement of Elm 0.17. 17 | * [Upgrading to 0.17][upgrade guide]: The official upgrade guide. 18 | * [Introduction to Elm][guide]: The official guide to the Elm 0.17 language and core packages. 19 | 20 | Others have written about the conversion as well: 21 | 22 | * [Migrating signal usage from Elm 0.16 to 0.17](http://noredink.github.io/posts/signalsmigration.html) 23 | 24 | ### Why does elm-make complain "Cannot find module 'Basics'"? 25 | 26 | You need to install the elm-lang/core package. 27 | 28 | This often arises when upgrading a package from 0.16 after removing all dependencies from elm-package.json. 29 | 30 | ### Where is the evancz/elm-html package? 31 | 32 | It's now at elm-lang/html. See the [upgrade guide] about this and other core packages that moved. 33 | 34 | [farewell]: http://elm-lang.org/blog/farewell-to-frp 35 | [upgrade guide]: https://github.com/elm-lang/elm-platform/blob/master/upgrade-docs/0.17.md 36 | [guide]: http://guide.elm-lang.org/ 37 | 38 | ### Where is `Effects.task`? 39 | 40 | It's gone. `Task.perform` is used instead. 41 | 42 | See some examples of [how to convert to Task.perform](17-tasks.html). 43 | 44 | ### Why am I getting "TypeError: Elm.embed is not a function"? 45 | 46 | The JavaScript code for calling the Elm entry point must now look like this: 47 | 48 | ```javascript 49 | Elm.MyApp.embed(someElement); 50 | ``` 51 | 52 | It used to look like `Elm.embed(Elm.MyApp, someElement)`. 53 | 54 | It's similar for the `fullscreen` and `worker` functions. 55 | 56 | ### What happened to all the core modules? 57 | 58 | Many core modules have been moved out into separate packages, usually under `elm-lang`. 59 | 60 | * `Graphics` is now in `evancz/elm-graphics` 61 | * `Trampoline` is now in `elm-lang/trampoline` and has some renames 62 | * `Trampoline.trampoline` is now `Trampoline.evaluate` 63 | * `Trampoline.Done` is now `Trampoline.done` (function instead of constructor) 64 | * `Trampoline.Continue` is now `Trampoline.jump` (function instead of constructor) 65 | * `Mouse` is now in `elm-lang/mouse` 66 | * `Window` is now in `elm-lang/window` 67 | * `Keyboard` is now in `elm-lang/keyboard` 68 | 69 | Also: 70 | 71 | * `maxsnew/lazy` is now `elm-lang/lazy` 72 | 73 | ### What is now in elm-community? 74 | 75 | * `NoRedInk/elm-lazy-list` is now `elm-community/elm-lazy-list` 76 | * `NoRedInk/elm-random-extra` is now `elm-community/random-extra` 77 | * `Random.Bool` has been removed as it is now in `elm-lang/core`'s `Random` 78 | * `Random.Function` has been removed entirely 79 | * `deadfoxygrandpa/elm-test` is now `elm-community/elm-test` 80 | * It no longer depends on `laszlopandy/elm-console`. To run tests in node use: `ElmTest.runSuite` 81 | * `elementRunner` is gone, use `runSuiteHtml` instead 82 | 83 | ### Why am I getting "cannot find module" errors while upgrading a project from 0.16? 84 | 85 | Cached or obsolete/renamed package versions may be getting in the way. To get a clean start, try these (from simplest to most drastic): 86 | 87 | 1. Remove all of elm-stuff. 88 | 2. Remove all the package names from the `dependencies` section of elm-package.json and install packages again as needed. You may have to explicitly install elm-lang/core again. 89 | 3. Remove all of ~/.elm (on linux or Mac OSX) or ~/AppData/Roaming/elm/package (on Windows). 90 | 91 | ### Does hot-reloading work in elm-reactor now? 92 | 93 | Not yet. Work is well underway to improve elm-reactor. 94 | 95 | ### Why does the compiler complain about "I am looking for one of the following things: whitespace" near the beginning of the file? 96 | 97 | The `exposing` clause is now required at the beginning of each module. 98 | For example, you now need `module Foo exposing (..)` where prior to Elm 0.17 you could use `module Foo where`. 99 | 100 | 101 | ### Are static ports still available? 102 | 103 | No. In Elm 0.17 you'll have to pass any static data from JS to Elm via the "flags" argument to the `embed()`, `fullscreen()`, or `worker()` functions. 104 | 105 | ### Why does elm-make report "I cannot find module 'Graphics.Collage'" even though evancz/elm-graphics is installed? 106 | 107 | You now need to do `import Collage` to get that module. It's no longer namespaced under `Graphics`. 108 | 109 | 110 | ## Footnotes 111 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | faq.elm-community.org 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'github-pages' 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Serve a local copy of the FAQ 2 | show: 3 | bundle exec jekyll serve 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elm-faq 2 | ## FAQ about the Elm language. 3 | 4 | Here are some [questions and answers](https://elm-community.github.io/elm-faq/) often seen on the #elm IRC channel on freenode, 5 | on the Elm Slack, 6 | and on the [elm-discuss](https://groups.google.com/forum/#!forum/elm-discuss) group. 7 | 8 | We welcome contributions as pull requests. 9 | 10 | ## How to serve a development version of the FAQ 11 | 12 | ### Setup 13 | 14 | ```bash 15 | sudo gem install bundler 16 | git clone git@github.com:elm-community/elm-faq.git 17 | cd elm-faq 18 | bundle install 19 | ``` 20 | 21 | ### Serving 22 | 23 | ```bash 24 | cd elm-faq 25 | bundle exec jekyll serve 26 | ``` 27 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Site settings 2 | title: Elm (language) FAQ 3 | description: > # this means to ignore newlines until "baseurl:" 4 | Unofficial FAQ for the Elm language. 5 | #baseurl: "/elm-faq" # the subpath of your site, e.g. /blog/ 6 | #url: "http://yourdomain.com" # the base hostname & protocol for your site 7 | github_username: elm-community 8 | 9 | # Build settings 10 | markdown: kramdown 11 | 12 | # The following are supposed to be defaults per 13 | # https://help.github.com/articles/using-jekyll-with-pages/ but as of 2016-02-02 14 | # I have to set them explicitly for correct output. 15 | kramdown: 16 | input: GFM 17 | hard_wrap: false 18 | 19 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | 63 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /_includes/header.html: -------------------------------------------------------------------------------- 1 | 35 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include head.html %} 5 | 6 | 7 | 8 | {% include header.html %} 9 | 10 |
11 |
12 | {{ content }} 13 |
14 |
15 | 16 | {% include footer.html %} 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 | 6 |
7 |

{{ page.title }}

8 |
9 | 10 |
11 | {{ content }} 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /_layouts/post.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 | 6 |
7 |

{{ page.title }}

8 | 9 |
10 | 11 |
12 | {{ content }} 13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /_sass/_base.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Reset some basic elements 3 | */ 4 | body, h1, h2, h3, h4, h5, h6, 5 | p, blockquote, pre, hr, 6 | dl, dd, ol, ul, figure { 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | 12 | 13 | /** 14 | * Basic styling 15 | */ 16 | body { 17 | font-family: $base-font-family; 18 | font-size: $base-font-size; 19 | line-height: $base-line-height; 20 | font-weight: 300; 21 | color: $text-color; 22 | background-color: $background-color; 23 | -webkit-text-size-adjust: 100%; 24 | } 25 | 26 | 27 | 28 | /** 29 | * Set `margin-bottom` to maintain vertical rhythm 30 | */ 31 | h1, h2, h3, h4, h5, h6, 32 | p, blockquote, pre, 33 | ul, ol, dl, figure, 34 | %vertical-rhythm { 35 | margin-bottom: $spacing-unit / 2; 36 | } 37 | 38 | 39 | 40 | /** 41 | * Images 42 | */ 43 | img { 44 | max-width: 100%; 45 | vertical-align: middle; 46 | } 47 | 48 | 49 | 50 | /** 51 | * Figures 52 | */ 53 | figure > img { 54 | display: block; 55 | } 56 | 57 | figcaption { 58 | font-size: $small-font-size; 59 | } 60 | 61 | 62 | 63 | /** 64 | * Lists 65 | */ 66 | ul, ol { 67 | margin-left: $spacing-unit; 68 | } 69 | 70 | li { 71 | > ul, 72 | > ol { 73 | margin-bottom: 0; 74 | } 75 | } 76 | 77 | 78 | 79 | /** 80 | * Headings 81 | */ 82 | h1, h2, h3, h4, h5, h6 { 83 | font-weight: 300; 84 | } 85 | 86 | 87 | 88 | /** 89 | * Links 90 | */ 91 | a { 92 | color: $brand-color; 93 | text-decoration: none; 94 | 95 | &:visited { 96 | color: darken($brand-color, 15%); 97 | } 98 | 99 | &:hover { 100 | color: $text-color; 101 | text-decoration: underline; 102 | } 103 | } 104 | 105 | 106 | 107 | /** 108 | * Blockquotes 109 | */ 110 | blockquote { 111 | color: $grey-color; 112 | border-left: 4px solid $grey-color-light; 113 | padding-left: $spacing-unit / 2; 114 | font-size: 18px; 115 | letter-spacing: -1px; 116 | font-style: italic; 117 | 118 | > :last-child { 119 | margin-bottom: 0; 120 | } 121 | } 122 | 123 | 124 | 125 | /** 126 | * Code formatting 127 | */ 128 | pre, 129 | code { 130 | font-size: 15px; 131 | /* border: 1px solid $grey-color-light; */ 132 | border-radius: 3px; 133 | background-color: rgb(247, 247, 247); 134 | } 135 | 136 | code { 137 | padding: 1px 5px; 138 | } 139 | 140 | pre { 141 | padding: 8px 12px; 142 | overflow: auto; 143 | 144 | > code { 145 | border: 0; 146 | padding-right: 0; 147 | padding-left: 0; 148 | } 149 | } 150 | 151 | 152 | 153 | /** 154 | * Wrapper 155 | */ 156 | .wrapper { 157 | max-width: -webkit-calc(800px - (#{$spacing-unit} * 2)); 158 | max-width: calc(800px - (#{$spacing-unit} * 2)); 159 | margin-right: auto; 160 | margin-left: auto; 161 | padding-right: $spacing-unit; 162 | padding-left: $spacing-unit; 163 | @extend %clearfix; 164 | 165 | @include media-query($on-laptop) { 166 | max-width: -webkit-calc(800px - (#{$spacing-unit})); 167 | max-width: calc(800px - (#{$spacing-unit})); 168 | padding-right: $spacing-unit / 2; 169 | padding-left: $spacing-unit / 2; 170 | } 171 | } 172 | 173 | 174 | 175 | /** 176 | * Clearfix 177 | */ 178 | %clearfix { 179 | 180 | &:after { 181 | content: ""; 182 | display: table; 183 | clear: both; 184 | } 185 | } 186 | 187 | 188 | 189 | /** 190 | * Icons 191 | */ 192 | .icon { 193 | 194 | > svg { 195 | display: inline-block; 196 | width: 16px; 197 | height: 16px; 198 | vertical-align: middle; 199 | 200 | path { 201 | fill: $grey-color; 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /_sass/_custom.scss: -------------------------------------------------------------------------------- 1 | .precedence { 2 | td { padding: .5em; border-right: 1px solid lightgrey; } 3 | tr { margin: 0; padding: 0; } 4 | border-collapse: collapse; 5 | } 6 | 7 | table.task-conversions { 8 | margin-bottom: 2em; 9 | border-top: 1px solid lightgrey; 10 | border-bottom: 1px solid lightgrey; 11 | code { 12 | font-size: 80%; 13 | } 14 | td { 15 | padding-top: 1em; 16 | padding-bottom: 1em; 17 | } 18 | } 19 | 20 | input.filter { 21 | margin-bottom: 1em; 22 | margin-left: 3em; 23 | } 24 | 25 | ul.section-list { 26 | list-style-type: none; 27 | li { padding-top: 1em; } 28 | } 29 | -------------------------------------------------------------------------------- /_sass/_layout.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Site header 3 | */ 4 | .site-header { 5 | border-top: 5px solid $grey-color-dark; 6 | border-bottom: 1px solid $grey-color-light; 7 | min-height: 56px; 8 | 9 | // Positioning context for the mobile navigation icon 10 | position: relative; 11 | } 12 | 13 | .site-title { 14 | font-size: 26px; 15 | line-height: 56px; 16 | letter-spacing: -1px; 17 | margin-bottom: 0; 18 | float: left; 19 | 20 | &, 21 | &:visited { 22 | color: $grey-color-dark; 23 | } 24 | } 25 | 26 | .site-nav { 27 | float: right; 28 | line-height: 56px; 29 | 30 | .menu-icon { 31 | display: none; 32 | } 33 | 34 | .page-link { 35 | color: $text-color; 36 | line-height: $base-line-height; 37 | 38 | // Gaps between nav items, but not on the first one 39 | &:not(:first-child) { 40 | margin-left: 20px; 41 | } 42 | } 43 | 44 | @include media-query($on-palm) { 45 | position: absolute; 46 | top: 9px; 47 | right: 30px; 48 | background-color: $background-color; 49 | border: 1px solid $grey-color-light; 50 | border-radius: 5px; 51 | text-align: right; 52 | 53 | .menu-icon { 54 | display: block; 55 | float: right; 56 | width: 36px; 57 | height: 26px; 58 | line-height: 0; 59 | padding-top: 10px; 60 | text-align: center; 61 | 62 | > svg { 63 | width: 18px; 64 | height: 15px; 65 | 66 | path { 67 | fill: $grey-color-dark; 68 | } 69 | } 70 | } 71 | 72 | .trigger { 73 | clear: both; 74 | display: none; 75 | } 76 | 77 | &:hover .trigger { 78 | display: block; 79 | padding-bottom: 5px; 80 | } 81 | 82 | .page-link { 83 | display: block; 84 | padding: 5px 10px; 85 | } 86 | } 87 | } 88 | 89 | .logo { 90 | float: left; 91 | padding-right: 20px; 92 | img { 93 | height: 80px; 94 | } 95 | } 96 | 97 | 98 | /** 99 | * Site footer 100 | */ 101 | .site-footer { 102 | border-top: 1px solid $grey-color-light; 103 | padding: $spacing-unit 0; 104 | } 105 | 106 | .footer-heading { 107 | font-size: 18px; 108 | margin-bottom: $spacing-unit / 2; 109 | } 110 | 111 | .contact-list, 112 | .social-media-list { 113 | list-style: none; 114 | margin-left: 0; 115 | } 116 | 117 | .footer-col-wrapper { 118 | font-size: 15px; 119 | color: $grey-color; 120 | margin-left: -$spacing-unit / 2; 121 | @extend %clearfix; 122 | } 123 | 124 | .footer-col { 125 | float: left; 126 | margin-bottom: $spacing-unit / 2; 127 | padding-left: $spacing-unit / 2; 128 | } 129 | 130 | .footer-col-1 { 131 | width: -webkit-calc(35% - (#{$spacing-unit} / 2)); 132 | width: calc(35% - (#{$spacing-unit} / 2)); 133 | } 134 | 135 | .footer-col-2 { 136 | width: -webkit-calc(20% - (#{$spacing-unit} / 2)); 137 | width: calc(20% - (#{$spacing-unit} / 2)); 138 | } 139 | 140 | .footer-col-3 { 141 | width: -webkit-calc(45% - (#{$spacing-unit} / 2)); 142 | width: calc(45% - (#{$spacing-unit} / 2)); 143 | } 144 | 145 | @include media-query($on-laptop) { 146 | .footer-col-1, 147 | .footer-col-2 { 148 | width: -webkit-calc(50% - (#{$spacing-unit} / 2)); 149 | width: calc(50% - (#{$spacing-unit} / 2)); 150 | } 151 | 152 | .footer-col-3 { 153 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 154 | width: calc(100% - (#{$spacing-unit} / 2)); 155 | } 156 | } 157 | 158 | @include media-query($on-palm) { 159 | .footer-col { 160 | float: none; 161 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 162 | width: calc(100% - (#{$spacing-unit} / 2)); 163 | } 164 | } 165 | 166 | 167 | 168 | /** 169 | * Page content 170 | */ 171 | .page-content { 172 | padding: $spacing-unit 0; 173 | } 174 | 175 | .page-heading { 176 | font-size: 20px; 177 | } 178 | 179 | .post-list { 180 | margin-left: 0; 181 | list-style: none; 182 | 183 | > li { 184 | margin-bottom: $spacing-unit; 185 | } 186 | } 187 | 188 | .post-meta { 189 | font-size: $small-font-size; 190 | color: $grey-color; 191 | } 192 | 193 | .post-link { 194 | display: block; 195 | font-size: 24px; 196 | } 197 | 198 | 199 | 200 | /** 201 | * Posts 202 | */ 203 | .post-header { 204 | margin-bottom: $spacing-unit; 205 | } 206 | 207 | .post-title { 208 | font-size: 42px; 209 | letter-spacing: -1px; 210 | line-height: 1; 211 | 212 | @include media-query($on-laptop) { 213 | font-size: 36px; 214 | } 215 | } 216 | 217 | .post-content { 218 | margin-bottom: $spacing-unit; 219 | 220 | h2 { 221 | font-size: 32px; 222 | 223 | @include media-query($on-laptop) { 224 | font-size: 28px; 225 | } 226 | 227 | margin-top: 2em; 228 | 229 | } 230 | 231 | h3 { 232 | font-size: 26px; 233 | 234 | @include media-query($on-laptop) { 235 | font-size: 22px; 236 | } 237 | 238 | margin-top: 2em; 239 | 240 | } 241 | 242 | h4 { 243 | font-size: 20px; 244 | 245 | @include media-query($on-laptop) { 246 | font-size: 18px; 247 | } 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /_sass/_syntax-highlighting.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Syntax highlighting styles 3 | */ 4 | .highlight { 5 | ////background: #fff; 6 | @extend %vertical-rhythm; 7 | 8 | .c { color: #998; font-style: italic } // Comment 9 | .err { color: #a61717; background-color: #e3d2d2 } // Error 10 | .k { font-weight: bold } // Keyword 11 | .o { font-weight: bold } // Operator 12 | .cm { color: #998; font-style: italic } // Comment.Multiline 13 | .cp { color: #999; font-weight: bold } // Comment.Preproc 14 | .c1 { color: #998; font-style: italic } // Comment.Single 15 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special 16 | .gd { color: #000; background-color: #fdd } // Generic.Deleted 17 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific 18 | .ge { font-style: italic } // Generic.Emph 19 | .gr { color: #a00 } // Generic.Error 20 | .gh { color: #999 } // Generic.Heading 21 | .gi { color: #000; background-color: #dfd } // Generic.Inserted 22 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific 23 | .go { color: #888 } // Generic.Output 24 | .gp { color: #555 } // Generic.Prompt 25 | .gs { font-weight: bold } // Generic.Strong 26 | .gu { color: #aaa } // Generic.Subheading 27 | .gt { color: #a00 } // Generic.Traceback 28 | .kc { font-weight: bold } // Keyword.Constant 29 | .kd { font-weight: bold } // Keyword.Declaration 30 | .kp { font-weight: bold } // Keyword.Pseudo 31 | .kr { font-weight: bold } // Keyword.Reserved 32 | .kt { color: #458; font-weight: bold } // Keyword.Type 33 | .m { color: #099 } // Literal.Number 34 | .s { color: #d14 } // Literal.String 35 | .na { color: #008080 } // Name.Attribute 36 | .nb { color: #0086B3 } // Name.Builtin 37 | .nc { color: #458; font-weight: bold } // Name.Class 38 | .no { color: #008080 } // Name.Constant 39 | .ni { color: #800080 } // Name.Entity 40 | .ne { color: #900; font-weight: bold } // Name.Exception 41 | .nf { color: #900; font-weight: bold } // Name.Function 42 | .nn { color: #555 } // Name.Namespace 43 | .nt { color: #000080 } // Name.Tag 44 | .nv { color: #008080 } // Name.Variable 45 | .ow { font-weight: bold } // Operator.Word 46 | .w { color: #bbb } // Text.Whitespace 47 | .mf { color: #099 } // Literal.Number.Float 48 | .mh { color: #099 } // Literal.Number.Hex 49 | .mi { color: #099 } // Literal.Number.Integer 50 | .mo { color: #099 } // Literal.Number.Oct 51 | .sb { color: #d14 } // Literal.String.Backtick 52 | .sc { color: #d14 } // Literal.String.Char 53 | .sd { color: #d14 } // Literal.String.Doc 54 | .s2 { color: #d14 } // Literal.String.Double 55 | .se { color: #d14 } // Literal.String.Escape 56 | .sh { color: #d14 } // Literal.String.Heredoc 57 | .si { color: #d14 } // Literal.String.Interpol 58 | .sx { color: #d14 } // Literal.String.Other 59 | .sr { color: #009926 } // Literal.String.Regex 60 | .s1 { color: #d14 } // Literal.String.Single 61 | .ss { color: #990073 } // Literal.String.Symbol 62 | .bp { color: #999 } // Name.Builtin.Pseudo 63 | .vc { color: #008080 } // Name.Variable.Class 64 | .vg { color: #008080 } // Name.Variable.Global 65 | .vi { color: #008080 } // Name.Variable.Instance 66 | .il { color: #099 } // Literal.Number.Integer.Long 67 | } 68 | -------------------------------------------------------------------------------- /assets/anchor.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * AnchorJS - v3.2.2 - 2016-10-05 3 | * https://github.com/bryanbraun/anchorjs 4 | * Copyright (c) 2016 Bryan Braun; Licensed MIT 5 | */ 6 | !function(A,e){"use strict";"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():(A.AnchorJS=e(),A.anchors=new A.AnchorJS)}(this,function(){"use strict";function A(A){function e(A){A.icon=A.hasOwnProperty("icon")?A.icon:"",A.visible=A.hasOwnProperty("visible")?A.visible:"hover",A.placement=A.hasOwnProperty("placement")?A.placement:"right",A.class=A.hasOwnProperty("class")?A.class:"",A.truncate=A.hasOwnProperty("truncate")?Math.floor(A.truncate):64}function t(A){var e;if("string"==typeof A||A instanceof String)e=[].slice.call(document.querySelectorAll(A));else{if(!(Array.isArray(A)||A instanceof NodeList))throw new Error("The selector provided to AnchorJS was invalid.");e=[].slice.call(A)}return e}function n(){if(null===document.head.querySelector("style.anchorjs")){var A,e=document.createElement("style"),t=" .anchorjs-link { opacity: 0; text-decoration: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }",n=" *:hover > .anchorjs-link, .anchorjs-link:focus { opacity: 1; }",i=' @font-face { font-family: "anchorjs-icons"; src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype"); }',o=" [data-anchorjs-icon]::after { content: attr(data-anchorjs-icon); }";e.className="anchorjs",e.appendChild(document.createTextNode("")),A=document.head.querySelector('[rel="stylesheet"], style'),void 0===A?document.head.appendChild(e):document.head.insertBefore(e,A),e.sheet.insertRule(t,e.sheet.cssRules.length),e.sheet.insertRule(n,e.sheet.cssRules.length),e.sheet.insertRule(o,e.sheet.cssRules.length),e.sheet.insertRule(i,e.sheet.cssRules.length)}}this.options=A||{},this.elements=[],e(this.options),this.isTouchDevice=function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)},this.add=function(A){var i,o,s,c,r,a,h,l,u,d,f,p,w=[];if(e(this.options),p=this.options.visible,"touch"===p&&(p=this.isTouchDevice()?"always":"hover"),A||(A="h1, h2, h3, h4, h5, h6"),i=t(A),0===i.length)return!1;for(n(),o=document.querySelectorAll("[id]"),s=[].map.call(o,function(A){return A.id}),r=0;r-1,t=A.lastChild&&(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ")>-1;return e||t||!1}}return A}); 7 | -------------------------------------------------------------------------------- /assets/filter.js: -------------------------------------------------------------------------------- 1 | var container = document.getElementById('elm-content'); 2 | 3 | // Collect information about the implicit sections of the document. Each section 4 | // starts with an H3 element and continues until the next heading of equal or 5 | // higher value. 6 | 7 | var h3s = document.getElementsByTagName("H3"); 8 | var h3sArr = [].slice.call(h3s); // convert to array to allow map() 9 | 10 | var h3sInfo = h3sArr.map( function(elmt, index) { 11 | var title = elmt.innerText || elmt.textContent; 12 | 13 | var content = ""; 14 | for (var next = elmt.nextSibling; next; next = next.nextSibling) { 15 | if (next.tagName == "H3" || next.tagName == "H2" || next.tagName == "H1") { 16 | break; 17 | } 18 | content += next.textContent; 19 | } 20 | 21 | return { id: elmt.id, title: title, content: content }; 22 | }); 23 | 24 | 25 | Elm.Filter.embed(container, h3sInfo); 26 | 27 | // When following a link to the comprising page with a hash (HTML anchor 28 | // name) the browser often scrolls to the wrong offset in the document, as 29 | // if the content inserted by the Filter app above was not accounted 30 | // for. The following kluge works around that. 31 | 32 | if (window.location.hash) { 33 | var save = window.location.hash; 34 | window.location.hash = ""; 35 | setTimeout(function() { 36 | window.location.hash = save; 37 | }, 0); 38 | } 39 | -------------------------------------------------------------------------------- /assets/tangram-runner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-community/elm-faq/b206a27b53312be107d15e77f49636c2374587f1/assets/tangram-runner.png -------------------------------------------------------------------------------- /css/main.scss: -------------------------------------------------------------------------------- 1 | --- 2 | # Only the main Sass file needs front matter (the dashes are enough) 3 | --- 4 | @charset "utf-8"; 5 | 6 | 7 | 8 | // Our variables 9 | $base-font-family: Helvetica, Arial, sans-serif; 10 | $base-font-size: 16px; 11 | $small-font-size: $base-font-size * 0.875; 12 | $base-line-height: 1.5; 13 | 14 | $spacing-unit: 30px; 15 | 16 | $text-color: #111; 17 | $background-color: #fdfdfd; 18 | $brand-color: #2a7ae2; 19 | 20 | $grey-color: #828282; 21 | $grey-color-light: lighten($grey-color, 40%); 22 | $grey-color-dark: darken($grey-color, 25%); 23 | 24 | $on-palm: 600px; 25 | $on-laptop: 800px; 26 | 27 | 28 | 29 | // Using media queries with like this: 30 | // @include media-query($palm) { 31 | // .wrapper { 32 | // padding-right: $spacing-unit / 2; 33 | // padding-left: $spacing-unit / 2; 34 | // } 35 | // } 36 | @mixin media-query($device) { 37 | @media screen and (max-width: $device) { 38 | @content; 39 | } 40 | } 41 | 42 | 43 | 44 | // Import partials from `sass_dir` (defaults to `_sass`) 45 | @import 46 | "base", 47 | "layout", 48 | "syntax-highlighting" 49 | , "custom" 50 | ; 51 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elm-community/elm-faq/b206a27b53312be107d15e77f49636c2374587f1/favicon.ico -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Elm FAQ 3 | layout: page 4 | --- 5 | 6 | **This page is mostly for folks _learning_ Elm.** It aggregates questions that are commonly 7 | asked on [the Slack channel][slack], [the IRC channel][irc], or [Discourse][discourse]. 8 | Those are all friendly and helpful places to go if you do not find the answer to your 9 | question here! 10 | 11 | [slack]: http://elmlang.herokuapp.com/ 12 | [irc]: http://webchat.freenode.net/?channels=elm 13 | [discourse]: https://discourse.elm-lang.org/ 14 | 15 | - Contributions to [this document](https://github.com/elm-community/elm-faq) 16 | are welcome! 17 | 18 | - This document is about the current version of Elm (0.19 / 0.19.1). See also the 19 | [Elm 0.17 FAQ](17.html) about upgrading to Elm 0.17. See the [Elm 0.16 FAQ](16.html) 20 | about that older version of Elm. 21 | 22 | #### Contents 23 | 24 |
25 | 26 | ### What is the difference between `type` and `type alias`? 27 | 28 | `type` defines and names a new type (which behaves like an enum with data 29 | attached), and `type alias` gives a name to an existing type. 30 | 31 | `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](https://groups.google.com/forum/#!topic/elm-discuss/YgRqI5s2S7Y) 32 | 33 | ### Why does elm repl (or elm make) report "cannot find module 'Html'"? 34 | 35 | You need to install the Html module: 36 | 37 | elm install elm/html 38 | 39 | Several modules are [available by default](https://package.elm-lang.org/packages/elm/core/latest/) 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`. 40 | 41 | ### How do I know what package name to use for `elm install`? 42 | 43 | Search on [package.elm-lang.org](https://package.elm-lang.org/) for the module name and use the package name that you find there. 44 | 45 | ### How can I write debugging information to the console? 46 | 47 | 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: 48 | 49 | ```haskell 50 | case Debug.log "action" action of 51 | ``` 52 | 53 | If you want to just log a message and value without using that value, try this in a `let` clause: 54 | 55 | ```haskell 56 | _ = Debug.log "my message" someValue 57 | ``` 58 | 59 | Also see [`Debug.todo`](https://package.elm-lang.org/packages/elm/core/latest/Debug#todo) 60 | which gets special treatment from the compiler to provide additional information in the output. 61 | 62 | ### How do I install an older version of Elm, 0.16 for example? 63 | 64 | npm install -g elm@0.16 65 | 66 | If you need to switch between multiple versions of elm, consider [elmenv](https://github.com/sonnym/elmenv). 67 | 68 | ### What's the difference between `Html Msg` and `Html msg`? 69 | 70 | `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". 71 | 72 | ### How can I output literal HTML and avoid escaping of entities? 73 | 74 | We used to use the `innerHTML` property for this, but Elm 0.19 no longer allows that. 75 | 76 | See [issue #172](https://github.com/elm/html/issues/172) for discussion of the issue and possible solutions. 77 | 78 | ### What does `()` mean? 79 | 80 | It is the empty tuple or [unit type](https://en.wikipedia.org/wiki/Unit_type). It serves much like `void`, `null`, or `None` in other languages. 81 | 82 | ### What good is the `<|` operator if it is just function application? 83 | 84 | 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`. [^application] 85 | 86 | [^application]: Function application and the `<|` operator are discussed at some length [here](https://groups.google.com/d/msg/elm-discuss/-PLj_eamKVQ/Zzo7iNx2FgAJ). 87 | 88 | Note: The `<|` operator is essentially the same as `$` in Haskell. 89 | 90 | ### What are the Elm operator precedences and associativities? 91 | 92 | See an [Elm operator precedence table](operators.html). 93 | See also [Basics.elm](https://github.com/elm/core/blob/master/src/Basics.elm). 94 | 95 | ### How can I use multiple Elm programs on the same page? 96 | 97 | You can compile multiple modules into a single elm.js and then instantiate whatever module you need on the appropriate div. [^multiplemodules] For example, bundle multiple main programs (without duplicating any code) into a single elm.js like this: 98 | 99 | elm make Header.elm Footer.elm Login.elm --output=elm.js 100 | 101 | and then use them like this: 102 | 103 | var header = Elm.Header.init({ node: document.getElementById('header') }); 104 | var login = Elm.Footer.init({ node: document.getElementById('login') }); 105 | var footer = Elm.Login.init({ node: document.getElementById('footer') }); 106 | 107 | [^multiplemodules]: 108 | 109 | Use of multiple main modules in one application is discussed 110 | [here](https://groups.google.com/d/msg/elm-discuss/eEJgNnl99ps/keWXnn1KCwAJ) 111 | and [here](https://www.reddit.com/r/elm/comments/5vh1fi/where_do_you_suffer_most_while_programming_in_elm/deb93ay/). 112 | 113 | ### Does the main module file have to be named "Main.elm"? 114 | 115 | 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. 116 | 117 | For example, if both Foo.elm and Bar.elm contain an appropriate binding of `main`, 118 | compiling via `elm make Foo.elm Bar.elm --output=elm.js` creates an elm.js file 119 | such that both `Elm.Foo.init({ node: someElement })` and 120 | `Elm.Bar.init({ node: someOtherElement })` can be used from the same HTML file. 121 | 122 | ### Why, when I import a module that defines a type, does the compiler know about the type name but not its constructors? 123 | 124 | You need to import the module in one of the following ways: 125 | 126 | import MyModule exposing (MyType(..)) -- import type and constructors 127 | import MyModule exposing (MyType) -- import only the type, but no constructors. 128 | 129 | Similarly, the module itself may export none, or all of a type's constructors. 130 | 131 | module MyModule exposing (MyType(..)) -- exposes all constructors 132 | module MyModule exposing (MyType) -- exposes only MyType, but no constructors. 133 | 134 | Just exposing `MyType` without the `(..)` will leave the constructors undefined. There are reasons for [keeping tags and record constructors secret](http://package.elm-lang.org/help/design-guidelines#keep-tags-and-record-constructors-secret). 135 | 136 | ### Where can I use type annotations? 137 | 138 | In addition to the top-level, type annotations can also be applied to `let` expressions. 139 | 140 | ```haskell 141 | let 142 | hypotenuse : Float -> Float -> Float 143 | hypotenuse a b = 144 | sqrt (a^2 + b^2) 145 | in 146 | hypotenuse 3 4 147 | ``` 148 | 149 | ### How can I join the elmlang.slack.com community? 150 | 151 | Sign up at [elmlang.herokuapp.com](https://elmlang.herokuapp.com/). 152 | 153 | ### How can I recover when elm make fails with errors like "... openFile: does not exist"? 154 | 155 | That can happen when switching between elm versions. Try removing all of elm-stuff or just the build-artifacts: 156 | 157 | rm -r elm-stuff/build-artifacts 158 | 159 | ### How do I install an Elm package that has not been published to packages.elm-lang.org for use in my project? 160 | 161 | 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. 162 | 163 | ### How can I parse Json into Elm data? 164 | 165 | Currently you have to write the [parsing 166 | code](https://package.elm-lang.org/packages/elm/json/latest/Json-Decode). 167 | Other than for [data passed over ports](https://guide.elm-lang.org/interop/ports.html) there is no automatic conversion (and even 168 | there, experts recommend writing the parser manually to be able to handle error 169 | cases). 170 | 171 | ### How can I pass a record/object over ports? 172 | 173 | You have to declare the type of each of its values. 174 | 175 | ```elm 176 | port outgoing : { floatValue : Float, stringValue : String } -> Cmd msg 177 | 178 | port incoming : ({ intValue : Int, stringValue : String } -> msg) -> Sub msg 179 | ``` 180 | 181 | ### How can I report a compiler error message that could be better? 182 | 183 | Report the problem at the [error-message-catalog issue tracker](https://github.com/elm/error-message-catalog/issues) 184 | with a [short, self-contained, correct, example](http://sscce.org/) showing both the program and the problematic error messages. 185 | 186 | ### Does Elm have HashMaps? 187 | 188 | The core [Dict](https://package.elm-lang.org/packages/elm/core/latest/Dict) package provides a dictionary mapping unique keys to values. There are some restrictions on key value types; in particular, records cannot be keys. 189 | 190 | ### Why does my app fail immediately with a console error of "Uncaught TypeError: Cannot read property 'appendChild' of null"? 191 | 192 | Make sure that you are calling Elm's javascript `embed` function _after_ the 193 | referenced container has been defined in the HTML file. 194 | 195 | Similarly, Elm's `fullscreen` function should be called only after the page body has started. 196 | 197 | Good practice is to call `embed` or `fullscreen` at the end of the document body. 198 | 199 | ### How can I load CSS (or other resources) in elm reactor? 200 | 201 | It's not easy. Elm reactor can serve CSS files and so you can write a custom 202 | HTML file that links in your CSS and the elm.js generated by Elm and then load 203 | that HTML file in elm reactor. But you have to generate the elm.js outside of 204 | elm reactor; it is not automatically built or rebuilt on changes to the Elm source. 205 | 206 | When you click an Elm source file in elm reactor it compiles just that file (and 207 | any dependencies) and sends back the generated javascript which then runs and 208 | displays the full page view of the program. So to add any CSS you have to do it 209 | in the Elm program itself. Here is an example (thanks to @pdamoc): 210 | 211 | ```elm 212 | import Html exposing (..) 213 | import Html.Attributes exposing (..) 214 | 215 | withStyle html = 216 | div [] 217 | [ node "style" [type_ "text/css"] 218 | [text "@import url(https://cdnjs.cloudflare.com/ajax/libs/bulma/0.1.2/css/bulma.min.css)"] 219 | , html 220 | ] 221 | 222 | main = 223 | div [] 224 | [ a [class "button is-primary"] [text "Primary"] 225 | , a [class "button is-info"] [text "Info"] 226 | ] 227 | |> withStyle 228 | 229 | ``` 230 | 231 | For a more comprehensive solution, see the next question. 232 | 233 | ### How can I integrate Elm development into a larger app with CSS files and other resources? 234 | 235 | Elm-reactor is _not_ appropriate for that; it's geared toward simple pure-Elm applications. 236 | 237 | Consider using other hot-reload tools: 238 | [elm-live](https://github.com/tomekwi/elm-live), 239 | [elm-hot-loader](https://github.com/fluxxu/elm-hot-loader), 240 | [elm-webpack-starter](https://github.com/moarwick/elm-webpack-starter), 241 | [gulp-elm](https://github.com/philopon/gulp-elm/tree/master/example), or 242 | [devd](https://github.com/cortesi/devd). 243 | 244 | ### How does one render an HTML node conditionally? 245 | 246 | Use `Html.text ""` as an empty element. E.g. 247 | 248 | ```haskell 249 | if someCondition then 250 | Html.div [] [ {- ... some substantial Html value here ... -} ] 251 | else 252 | Html.text "" 253 | ``` 254 | 255 | ### Does Elm have ad-hoc polymorphism or typeclasses? 256 | 257 | No. Elm provides three super-types that work like typeclasses: 258 | `number`, `comparable`, and `appendable`. [^compappend] 259 | The Elm language does not allow for defining our own super-types. 260 | 261 | [^compappend]: There is also `compappend` in the compiler but it does not appear to be exposed for use. 262 | 263 | The `number` type comprises `Int` and `Float`. 264 | 265 | The `comparable` type comprises `Int`, `Float`, `Char`, `String`, `List`, and tuples[^tuple_compare]. 266 | 267 | [^tuple_compare]: Tuple comparison is supported only for tuples with 6 or fewer entries. 268 | 269 | The `appendable` type comprises `String`, `List`, and `text`[^text_append]. 270 | 271 | [^text_append]: The compiler error messages refer to `text` being appendable; not sure what `text` means though. [FCY] 272 | 273 | When declaring types the names `number`, `comparable` and `appendable` serve as prefixes. For example, a function declared as 274 | 275 | ```haskell 276 | f : number -> number -> String 277 | ``` 278 | 279 | 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. 280 | 281 | However, if declared as 282 | 283 | ```haskell 284 | f : number1 -> number2 -> String 285 | ``` 286 | 287 | 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. 288 | 289 | #### Why doesn't Elm have user-defined typeclasses? 290 | 291 | So far there have not been enough compelling cases to justify adding user-defined typeclasses to the language. 292 | See [compiler issue #1039](https://github.com/elm/compiler/issues/1039). 293 | 294 | ### Which special type variables are there, and how do they work? 295 | 296 | There are four special type vairables, which are `number`, `comparable`, `appendable`, and `compappend`. Please see question [Does Elm have ad-hoc polymorphism or typeclasses?](#does-elm-have-ad-hoc-polymorphism-or-typeclasses) for the details. 297 | 298 | 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: 299 | 300 | ```haskell 301 | type alias PlusFn t = 302 | { fn: t -> t -> t 303 | } 304 | ``` 305 | 306 | 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. 307 | 308 | ```haskell 309 | > PlusFn (\x y -> x + y) 310 | { fn = } : Repl.PlusFn number 311 | > PlusFn (\x y -> x ++ y) 312 | { fn = } : Repl.PlusFn appendable 313 | ``` 314 | 315 | 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: 316 | 317 | ```haskell 318 | > PlusFn (\x y -> x ++ y) 319 | -- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm 320 | 321 | The argument to function `PlusFn` is causing a mismatch. 322 | 323 | 4| PlusFn (\x y -> x ++ y) 324 | ^^^^^^^^^^^^^^ 325 | Function `PlusFn` is expecting the argument to be: 326 | 327 | number -> number -> number 328 | 329 | But it is: 330 | 331 | appendable -> appendable -> appendable 332 | ``` 333 | 334 | ### How can I change the value of a field in a record? 335 | 336 | Strictly speaking, you can't. Record values (like all Elm values) are 337 | immutable. However, you can _copy_ a record value and change one or 338 | more of its field values while doing so. Here is an example in 339 | elm repl: 340 | 341 | ```haskell 342 | > x = { name = "Chris", age = 30 } 343 | { name = "Chris", age = 30 } : { name : String, age : number } 344 | > y = { x | age = x.age + 1 } 345 | { name = "Chris", age = 31 } : { name : String, age : number } 346 | > y 347 | { name = "Chris", age = 31 } : { name : String, age : number } 348 | > x 349 | { name = "Chris", age = 30 } : { name : String, age : number } 350 | ``` 351 | 352 | ### How can I change the value of a nested field? 353 | 354 | For example, given `model = { foo = { bar = 1 } }`, how does one update the value of the `bar` field? 355 | The expression `{ model | foo.bar = 2 }` will not compile. 356 | 357 | Here is an expression that returns a copy of `model` with `model.foo.bar` updated: 358 | 359 | `let foo = model.foo in { model | foo = { foo | bar = 2 } }` 360 | 361 | Or, perhaps more clearly, like this: 362 | 363 | `let fooBefore = model.foo in { model | foo = { fooBefore | bar = 2 } }` 364 | 365 | If you need to do this in more than one place, another way is to use a helper function: 366 | 367 | ```haskell 368 | { model | foo = updateHelp model.foo 2 } 369 | 370 | updateHelp foo int = 371 | { foo | bar = int } 372 | ``` 373 | 374 | ### How can I pattern match a record and its values at the same time? 375 | 376 | You can use a special notation in function definition to pattern match a record and its values at the same time: 377 | 378 | ```haskell 379 | changeFooBar ({foo} as model) = 380 | { model | foo = { foo | bar = 2 } } 381 | ``` 382 | 383 | See this [post](https://medium.com/elm-shorts/intro-to-records-in-elm-51bc5e933a57) 384 | 385 | ### Where are the `Cmd` and `Sub` types defined? 386 | 387 | They are defined in the core 388 | [Platform.Cmd](https://package.elm-lang.org/packages/elm/core/latest/Platform-Cmd) 389 | and 390 | [Platform.Sub](https://package.elm-lang.org/packages/elm/core/latest/Platform-Sub) 391 | modules. 392 | 393 | ### What is the difference between `Cmd Msg` and `Cmd msg`? 394 | 395 | `Cmd Msg` is a type of command where the resulting messages are of type `Msg`. 396 | 397 | `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`. 398 | 399 | ### Why does the compiler complain that "You are declaring port \`someName\` in a normal module."? 400 | 401 | Any module using ports must start with `port module` on the first line. 402 | 403 | ### How do I generate a new message as a command? 404 | 405 | The following function constructs a `Cmd` value from a message: 406 | 407 | ```haskell 408 | message : msg -> Cmd msg 409 | message msg = 410 | Task.perform identity (Task.succeed msg) 411 | ``` 412 | 413 | 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](http://package.elm-lang.org/packages/ccapndave/elm-update-extra/latest) provides helper functions for implementing this approach elegantly. 414 | 415 | 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. 416 | 417 | ### What is the difference between `Cmd` and `Task`? 418 | 419 | - `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`. 420 | 421 | - `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. 422 | 423 | 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.[^cmd-vs-task] 424 | 425 | [^cmd-vs-task]: From Evan's #elm-dev Slack posting, 2016-05-16. 426 | 427 | 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. 428 | 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`.[^task-chaining] 429 | 430 | [^task-chaining]: From rtfeldman's #elm-dev Slack posting, 2016-05-16. 431 | 432 | ### How do I build an `onChange` handler for a `