on master help sign in
move over all the compiler hints
08c956cEvan Czaplicki
hints/bad-recursion.mdnew file+136
@@ -0,0 +1,136 @@
1+
2+# Hints for Bad Recursion
3+
4+There are two problems that will lead you here, both of them pretty tricky:
5+
6+ 1. [**No Mutation**](#no-mutation) — Defining values in Elm is slightly different than defining values in languages like JavaScript.
7+
8+ 2. [**Tricky Recursion**](#tricky-recursion) — Sometimes you need to define recursive values. A common case is JSON decoders for things like discussion forums, where a comment may have replies, which may have replies, etc.
9+
10+
11+## No Mutation
12+
13+Languages like JavaScript let you “reassign” variables. When you say `x = x + 1` it means: whatever `x` was pointing to, have it point to `x + 1` instead. This called *mutating* a variable. All values are immutable in Elm, so reassigning variables does not make any sense! Okay, so what *should* `x = x + 1` mean in Elm?
14+
15+Well, what does it mean with functions? In Elm, we write recursive functions like this:
16+
17+```elm
18+factorial : Int -> Int
19+factorial n =
20+ if n <= 0 then 1 else n * factorial (n - 1)
21+```
22+
23+One cool thing about Elm is that whenever you see `factorial 3`, you can always replace that expression with `if 3 <= 0 then 1 else 3 * factorial (3 - 1)` and it will work exactly the same. So when Elm code gets evaluated, we will keep expanding `factorial` until the `if` produces a 1. At that point, we are done expanding and move on.
24+
25+The thing that surprises newcomers is that recursion works the same way with values too. So take the following definition:
26+
27+```elm
28+x = x + 1
29+```
30+
31+We are actually defining `x` in terms of itself. So it would expand out to `x = ... + 1 + 1 + 1 + 1`, trying to add one to `x` an infinite number of times! This means your program would just run forever, endlessly expanding `x`. In practice, this means the page freezes and the computer starts to get kind of warm. No good! We can detect cases like this with the compiler, so we give an error at compile time so this does not happen in the wild.
32+
33+The fix is usually to just give the new value a new name. So you could rewrite it to:
34+
35+```elm
36+x1 = x + 1
37+```
38+
39+Now `x` is the old value and `x1` is the new value. Again, one cool thing about Elm is that whenever you see a `factorial 3` you can safely replace it with its definition. Well, the same is true of values. Wherever I see `x1`, I can replace it with `x + 1`. Thanks to the way definitions work in Elm, this is always safe!
40+
41+
42+## Tricky Recursion
43+
44+Now, there are some cases where you *do* want a recursive value. Say you are building a website with comments and replies. You may define a comment like this:
45+
46+```elm
47+type alias Comment =
48+ { message : String
49+ , upvotes : Int
50+ , downvotes : Int
51+ , responses : Responses
52+ }
53+
54+type Responses = Responses (List Comment)
55+```
56+
57+You may have run into this definition in the [hints for recursive aliases](recursive-alias)! Anyway, once you have comments, you may want to turn them into JSON to send back to your server or to store in your database or whatever. So you will probably write some code like this:
58+
59+```elm
60+import Json.Decode as Decode exposing (Decoder)
61+
62+decodeComment : Decoder Comment
63+decodeComment =
64+ Decode.map4 Comment
65+ (Decode.field "message" Decode.string)
66+ (Decode.field "upvotes" Decode.int)
67+ (Decode.field "downvotes" Decode.int)
68+ (Decode.field "responses" decodeResponses)
69+
70+-- PROBLEM
71+decodeResponses : Decoder Responses
72+decodeResponses =
73+ Decode.map Responses (Decode.list decodeComment)
74+```
75+
76+The problem is that now `decodeComment` is defined in terms of itself! To know what `decodeComment` is, I need to expand `decodeResponses`. To know what `decodeResponses` is, I need to expand `decodeComment`. This loop will repeat endlessly!
77+
78+In this case, the trick is to use `Json.Decode.lazy` which delays the evaluation of a decoder until it is needed. So the valid definition would look like this:
79+
80+```elm
81+import Json.Decode as Decode exposing (Decoder)
82+
83+decodeComment : Decoder Comment
84+decodeComment =
85+ Decode.map4 Comment
86+ (Decode.field "message" Decode.string)
87+ (Decode.field "upvotes" Decode.int)
88+ (Decode.field "downvotes" Decode.int)
89+ (Decode.field "responses" decodeResponses)
90+
91+-- SOLUTION
92+decodeResponses : Decoder Responses
93+decodeResponses =
94+ Decode.map Responses (Decode.list (Decode.lazy (\\_ -> decodeComment)))
95+```
96+
97+Notice that in `decodeResponses`, we hide `decodeComment` behind an anonymous function. Elm cannot evaluate an anonymous function until it is given arguments. So it allows us to delay evaluation until it is needed. If there are no comments, we will not need to expand it!
98+
99+
100+### Summary
101+
102+**Situation:** You want a recursive JSON decoder, random value generator, or task. These are all cases where a *value* represents some sort of computation.
103+
104+**Solution:** put the recursion behind an anonymous function.
105+
106+You can always do this by defining `lazy` in terms of `andThen`. In the case of random value generators, it would look like this:
107+
108+```elm
109+import Random exposing (Generator, andThen)
110+import Random.Extra exposing (constant)
111+
112+lazy : (() -> Generator a) -> Generator a
113+lazy delayedGenerator =
114+ constant ()
115+ |> andThen delayedGenerator
116+```
117+
118+If you are in some situation where this will not work, I am curious to hear about it. I would recommend asking around in [the Elm slack](http://elmlang.herokuapp.com/) first, and opening an issue here if it seems to be the real deal!
119+
120+
121+## Defining “Bad” Recursion
122+
123+The compiler will yell at you for *bad* recursion, but how does it know the difference between good and bad situations? Writing `factorial` is fine, but writing `x = x + 1` is not. One version of `decodeComment` was bad, but the other was fine. What is the rule?
124+
125+**Elm will allow recursive definitions as long as there is at least one lambda before you get back to yourself.** So if we write `factorial` without any pretty syntax, it looks like this:
126+
127+```elm
128+factorial =
129+ \\n -> if n <= 0 then 1 else n * factorial (n - 1)
130+```
131+
132+There is technically a lambda between the definition and the use! The same is true with the good version of `decodeComment`. As long as there is a lambda before you get back to yourself, the compiler will let it through.
133+
134+This rule is nice, but it does not catch *everything*. Pathological cases like `x = (\\_ -> x) () + 1` can make it through. Why not rule these out as well though?! Well, because it is impossible! And not the normal kind of impossible where your cable bill is messed up and the fifth time you call it turns out it *can* be corrected. This is the &ldquo;we proved it with math, it’s called [the halting problem](https://en.wikipedia.org/wiki/Halting_problem)&rdquo; kind of impossible. Impossible [like this](https://www.youtube.com/watch?v=nlD9JYP8u5E).
135+
136+Anyway, I just thought it was cool that we cannot solve the halting problem *in general*, but a simple rule about lambdas can detect the majority of bad cases *in practice*.
hints/custom-types.mdnew file+1
@@ -0,0 +1 @@
1+# Custom Types
hints/docs.mdnew file+2
@@ -0,0 +1,2 @@
1+
2+# Docs
hints/implicit-casts.mdnew file+53
@@ -0,0 +1,53 @@
1+
2+# Implicit Casts
3+
4+Many languages automatically convert from `Int` to `Float` when they think it is necessary. This conversion is often called an [implicit cast](https://en.wikipedia.org/wiki/Type_conversion).
5+
6+Languages that will add in implicit casts for addition include:
7+
8+ - JavaScript
9+ - Python
10+ - Ruby
11+ - C
12+ - C++
13+ - C#
14+ - Java
15+ - Scala
16+
17+These languages generally agree that an `Int` may be implicitly cast to a `Float` when necessary. So everyone is doing it, why not Elm?!
18+
19+> **Note:** Ruby does not follow the trend. They implicitly cast a `Float` to an `Int`, truncating all the decimal points!
20+
21+
22+## Type Inference + Implicit Casts
23+
24+Elm comes from the ML-family of languages. Languages in the ML-family that **never** do implicit casts include:
25+
26+ - Standard ML
27+ - OCaml
28+ - Elm
29+ - F#
30+ - Haskell
31+
32+Why would so many languages from this lineage require explicit conversions though?
33+
34+Well, we have to go back to the 1970s for some background. J. Roger Hindley and Robin Milner independently discovered an algorithm that could _efficiently_ figure out the type of everything in your program without any type annotations. Type Inference! Every ML-family language has some variation of this algorithm at the center of its design.
35+
36+For decades, the problem was that nobody could figure out how to combine type inference with implicit casts AND make the resulting algorithm efficient enough for daily use. As far as I know, Scala was the first widely known language to figure out how to combine these two things! Its creator, Martin Odersky did a lot of work on combining type inference and subtyping to make this possible.
37+
38+So for any ML-family language designed before Scala, it is safe to assume that implicit conversions just was not an option. Okay, but what about Elm?! It comes after Scala, so why not do it like them?!
39+
40+ 1. You pay performance cost to mix type inference and implicit conversions. At least as far as anyone knows, it defeats an optimization that is crucial to getting _reliably_ good performance. It is fine in most cases, but it can be a real issue in very large code bases.
41+
42+ 2. Based on experience reports from Scala users, it seemed like the convenience was not worth the hidden cost. Yes, you can convert `n` in `(n + 1.5)` and everything is nice, but when you are in larger programs that are sparsely annotated, it can be quite difficult to figure out what is going on.
43+
44+This user data may be confounded by the fact that Scala allows quite extensive conversions, not just from `Int` to `Float`, but I think it is worth taking seriously nonetheless. So it is _possible_, but it is has tradeoffs.
45+
46+
47+## Conclusion
48+
49+First, based on the landscape of design possibilities, it seems like requiring _explicit_ conversions is a pretty nice balance. We can have type inference, it can produce friendly error messages, the algorithm is snappy, and an unintended implicit cast will not flow hundreds of lines before manifesting to the user.
50+
51+Second, Elm very much favors explicit code, so this also fits in with the overall spirit of the language and libraries.
52+
53+I hope that clarifies why you have to add those `toFloat` and `round` functions! It definitely can take some getting used to, but there are tons of folks who get past that acclimation period and really love the tradeoffs!
hints/import-cycles.mdnew file+184
@@ -0,0 +1,184 @@
1+
2+# Import Cycles
3+
4+What is an import cycle? In practice you may see it if you create two modules with interrelated `User` and `Comment` types like this:
5+
6+```elm
7+module Comment exposing (..)
8+
9+import User
10+
11+type alias Comment =
12+ { comment : String
13+ , author : User.User
14+ }
15+```
16+
17+```elm
18+module User exposing (..)
19+
20+import Comment
21+
22+type alias User =
23+ { name : String
24+ , comments : List Comment.Comment
25+ }
26+```
27+
28+Notice that to compile `Comment` we need to `import User`. And notice that to compile `User` we need to `import Comment`. We need both to compile either!
29+
30+Now this is *possible* if the compiler figures out any module cycles and puts them all in one big file to compile them together. That seems fine in our small example, but imagine we have a cycle of 20 modules. If you change *one* of them, you must now recompile *all* of them. In a large code base, this causes extremely long compile times. It is also very hard to disentangle them in practice, so you just end up with slow builds. That is your life now.
31+
32+The thing is that you can always write the code *without* cycles by shuffling declarations around, and the resulting code is often much clearer.
33+
34+
35+# How to Break Cycles
36+
37+There are quite a few ways to break our `Comment` and `User` cycle from above, so let’s go through four useful strategies. The first one is by far the most common solution!
38+
39+
40+## 1. Combine the Modules
41+
42+One approach is to just combine the two modules. If we check out the resulting code, we have actually revealed a problem in how we are representing our data:
43+
44+```elm
45+module BadCombination1 exposing (..)
46+
47+type alias Comment =
48+ { comment : String
49+ , author : User
50+ }
51+
52+type alias User =
53+ { name : String
54+ , comments : List Comment
55+ }
56+```
57+
58+Notice that the `Comment` type alias is defined in terms of the `User` type alias and vice versa. Having recursive type aliases like this does not work! That problem is described in depth [here](recursive-alias), but the quick takeaway is that one `type alias` needs to become a `type` to break the recursion. So let’s try again:
59+
60+```elm
61+module BadCombination2 exposing (..)
62+
63+type alias Comment =
64+ { comment : String
65+ , author : User
66+ }
67+
68+type alias User =
69+ { name : String
70+ , comments : AllUserComments
71+ }
72+
73+type AllUserComments = AllUserComments (List Comment)
74+```
75+
76+Okay, now we have broken the recursion, but we need to ask ourselves, how are we going to actually instantiate these `Comment` and `User` types that we have described. A `Comment` will always have an author, and that `User` will always refer back to the `Comment`. So we seem to want cyclic data here. If we were in JavaScript we might instantiate all the comments in one pass, and then go back through and mutate the users to point to all the relevant comments. In other words, we need *mutation* to create this cyclic data!
77+
78+All values are immutable in Elm, so we need to use a more functional strategy. One common approach is to use unique identifiers. Instead of referring directly to “the user object” we can refer to a user ID:
79+
80+```elm
81+module GoodCombination exposing (..)
82+
83+import Dict
84+
85+type alias Comment =
86+ { comment : String
87+ , author : UserId
88+ }
89+
90+type alias UserId = String
91+
92+type alias AllComments =
93+ Dict.Dict UserId (List Comment)
94+```
95+
96+Now in this world, we do not even have cycles in our types anymore! That means we can actually break these out into separate modules again:
97+
98+```elm
99+module Comment exposing (..)
100+
101+import Dict
102+import User
103+
104+type alias Comment =
105+ { comment : String
106+ , author : User.Id
107+ }
108+
109+type alias AllComments =
110+ Dict.Dict User.Id (List Comment)
111+```
112+
113+```elm
114+module User exposing (..)
115+
116+type alias Id = String
117+```
118+
119+So now we are back to the two modules we wanted, but we have data structures that are going to work much better in a functional language like Elm! **This is the common approach, and it is what you hope will happen!**
120+
121+
122+## 2. Make a New Module
123+
124+Now say there are actually a ton of functions and values in the `Comment` and `User` modules. Combining them into one does not seem like a good strategy. Instead you can create a *third* module that just has the shared types and functions. Let’s pretend we call that third module `GoodCombination`. So rather than having `Comment` and `User` depend on each other, they now both depend on `GoodCombination`. We broke our cycle!
125+
126+**This strategy is less common.** You generally want to keep the core `type` of a module with all the functions that act upon it directly, so separating a `type` from everything else is a bad sign. So maybe there is a `User` module that contains a bunch of helper functions, but you *use* all those helper functions in a bunch of other modules that interact with users in various ways. In that scenario, it is still more sophisticated than “just throw the types in a module together” and hope it turns out alright.
127+
128+
129+## 3. Use Type Variables
130+
131+Another way to avoid module cycles is to be more generic in how you represent your data:
132+
133+```elm
134+module Comment exposing (..)
135+
136+type alias Comment author =
137+ { comment : String
138+ , author : author
139+ }
140+```
141+
142+```elm
143+module User exposing (..)
144+
145+type alias User comment =
146+ { name : String
147+ , comments : List comment
148+ }
149+```
150+
151+Notice that `Comment` and `User` no longer need to import each other! Instead, whenever we use these modules, we need to fill in the type variable. So we may import both `Comment` and `User` and try to combine them into a `Comment (User (Comment (User ...)))`. Gah, we ran into the recursive type alias thing again!
152+
153+So this strategy fails pretty badly with our particular example. The code is more complicated and it still does not work! So **this strategy is rarely useful**, but when it works, it can simplify things quite a lot.
154+
155+
156+## 4. Hiding Implementation Details in Packages
157+
158+This gets a little bit trickier when you are creating a package like `elm-lang/parser` which is built around the `Parser` type.
159+
160+That package has a couple exposed modules: `Parser`, `Parser.LanguageKit`, and `Parser.LowLevel`. All of these modules want access to the internal details of the `Parser` type, but we do not want to ever expose those internal details to the *users* of this package. So where should the `Parser` type live?!
161+
162+Usually you know which module should expose the type for the best public API. In this case, it makes sense for it to live in the `Parser` module. The way to manage this is to create a `Parser.Internal` module with a definition like:
163+
164+```elm
165+module Parser.Internal exposing (..)
166+
167+type Parser a =
168+ Parser ...
169+```
170+
171+Now we can `import Parser.Internal` and use it in any of the modules in our package. The trick is that we never expose the `Parser.Internal` module to the *users* of our package. We can see what is inside, but they cannot! Then in the `Parser` module we can say:
172+
173+```elm
174+module Parser exposing (..)
175+
176+import Parser.Internal as Internal
177+
178+type alias Parser a =
179+ Internal.Parser a
180+```
181+
182+So now folks see a `Parser` type exposed by the `Parser` module, and it is the one that is used throughout all the modules in the package. Do not screw up your data representation to avoid this trick! I think we can improve how this appears in documentation, but overall this is the best way to go.
183+
184+Now again, this strategy is particularly useful in packages. It is not as worthwhile in application code.
hints/imports.mdnew file+126
@@ -0,0 +1,126 @@
1+
2+# Hints for Imports
3+
4+When getting started with Elm, it is pretty common to have questions about how the `import` declarations work exactly. These questions usually arise when you start playing with the `Html` library so we will focus on that.
5+
6+
7+<br>
8+
9+## `import`
10+
11+An Elm file is called a **module**. To access code in other files, you need to `import` it!
12+
13+So say you want to use the [`div`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html#div) function from the [`elm-lang/html`](http://package.elm-lang.org/packages/elm-lang/html/latest) package. The simplest way is to import it like this:
14+
15+```elm
16+import Html
17+
18+main =
19+ Html.div [] []
20+```
21+
22+After saying `import Html` we can refer to anything inside that module as long as it is *qualified*. This works for:
23+
24+ - **Values** &mdash; we can refer to `Html.text`, `Html.h1`, etc.
25+ - **Types** &mdash; We can refer to [`Attribute`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html#Attribute) as `Html.Attribute`.
26+
27+So if we add a type annotation to `main` it would look like this:
28+
29+```elm
30+import Html
31+
32+main : Html.Html msg
33+main =
34+ Html.div [] []
35+```
36+
37+We are referring to the [`Html`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html#Html) type, using its *qualified* name `Html.Html`. This can feel weird at first, but it starts feeling natural quite quickly!
38+
39+> **Note:** Modules do not contain other modules. So the `Html` module *does not* contain the `Html.Attributes` module. Those are separate names that happen to have some overlap. So if you say `import Html` you *do not* get access to `Html.Attributes.style`. You must `import Html.Attributes` module separately.
40+
41+
42+<br>
43+
44+## `as`
45+
46+It is best practice to always use *qualified* names, but sometimes module names are so long that it becomes unwieldy. This is common for the `Html.Attributes` module. We can use the `as` keyword to help with this:
47+
48+```elm
49+import Html
50+import Html.Attributes as A
51+
52+main =
53+ Html.div [ A.style "color" "red" ] [ Html.text "Hello!" ]
54+```
55+
56+Saying `import Html.Attributes as A` lets us refer to any value or type in `Html.Attributes` as long as it is qualified with an `A`. So now we can refer to [`style`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html-Attributes#style) as `A.style`.
57+
58+
59+<br>
60+
61+## `exposing`
62+
63+In quick drafts, maybe you want to use *unqualified* names. You can do that with the `exposing` keyword like this:
64+
65+```elm
66+import Html exposing (..)
67+import Html.Attributes exposing (style)
68+
69+main : Html msg
70+main =
71+ div [ style "color" "red" ] [ text "Hello!" ]
72+```
73+
74+Saying `import Html exposing (..)` means I can refer to any value or type from the `Html` module without qualification. Notice that I use the `Html` type, the `div` function, and the `text` function without qualification in the example above.
75+
76+> **Note:** It seems neat to expose types and values directly, but it can get out of hand. Say you `import` ten modules `exposing` all of their content. It quickly becomes difficult to figure out what is going on in your code. “Wait, where is this function from?” And then trying to sort through all the imports to find it. Point is, use `exposing (..)` sparingly!
77+
78+Saying `import Html.Attributes exposing (style)` is a bit more reasonable. It means I can refer to the `style` function without qualification, but that is it. You are still importing the `Html.Attributes` module like normal though, so you would say `Html.Attributes.class` or `Html.Attributes.id` to refer to other values and types from that module.
79+
80+
81+<br>
82+
83+## `as` and `exposing`
84+
85+There is one last way to import a module. You can combine `as` and `exposing` to try to get a nice balance of qualified names:
86+
87+```elm
88+import Html exposing (Html, div, text)
89+import Html.Attributes as A exposing (style)
90+
91+main : Html msg
92+main =
93+ div [ A.class "greeting", style "color" "red" ] [ text "Hello!" ]
94+```
95+
96+Notice that I refer to `A.class` which is qualified and `style` which is unqualified.
97+
98+
99+<br>
100+
101+## Default Imports
102+
103+We just learned all the variations of the `import` syntax in Elm. You will use some version of that syntax to `import` any module you ever write.
104+
105+It would be the best policy to make it so every module in the whole ecosystem works this way. We thought so in the past at least, but there are some modules that are so commonly used that the Elm compiler automatically adds the imports to every file. These default imports include:
106+
107+```elm
108+import Basics exposing (..)
109+import List exposing ( List, (::) )
110+import Maybe exposing ( Maybe( Just, Nothing ) )
111+import Result exposing ( Result( Ok, Err ) )
112+import String
113+import Tuple
114+
115+import Debug
116+
117+import Platform exposing ( Program )
118+import Platform.Cmd as Cmd exposing ( Cmd )
119+import Platform.Sub as Sub exposing ( Sub )
120+```
121+
122+You can think of these imports being at the top of any module you write.
123+
124+One could argue that `Maybe` is so fundamental to how we handle errors in Elm code that it is *basically* part of the language. One could also argue that it is extraordinarily annoying to have to import `Maybe` once you get past your first couple weeks with Elm. Either way, we know that default imports are not ideal in some sense, so we have tried to keep the default imports as minimal as possible.
125+
126+> **Note:** Elm performs dead code elimination, so if you do not use something from a module, it is not included in the generated code. So if you `import` a module with hundreds of functions, you do not need to worry about the size of your assets. You will only get what you use!
hints/infinite-type.mdnew file+42
@@ -0,0 +1,42 @@
1+
2+# Hints for Infinite Types
3+
4+Infinite types are probably the trickiest kind of bugs to track down. **Writing down type annotations is usually the fastest way to figure them out.** Let's work through an example to get a feel for how these errors usually work though!
5+
6+
7+## Example
8+
9+A common way to get an infinite type error is very small typos. For example, do you see the problem in the following code?
10+
11+```elm
12+incrementNumbers list =
13+ List.map incrementNumbers list
14+
15+incrementNumber n =
16+ n + 1
17+```
18+
19+The issue is that `incrementNumbers` calls itself, not the `incrementNumber` function defined below. So there is an extra `s` in this program! Let's focus on that:
20+
21+```elm
22+incrementNumbers list =
23+ List.map incrementNumbers list -- BUG extra `s` makes this self-recursive
24+```
25+
26+Now the compiler does not know that anything is wrong yet. It just tries to figure out the types like normal. It knows that `incrementNumbers` is a function. The definition uses `List.map` so we can deduce that `list : List t1` and the result of this function call should be some other `List t2`. This also means that `incrementNumbers : List t1 -> List t2`.
27+
28+The issue is that `List.map` uses `incrementNumbers` on `list`! That means that each element of `list` (which has type `t1`) must be fed into `incrementNumbers` (which takes `List t1`)
29+
30+That means that `t1 = List t1`, which is an infinite type! If we start expanding this, we get `List (List (List (List (List ...))))` out to infinity!
31+
32+The point is mainly that we are in a confusing situation. The types are confusing. This explanation is confusing. The compiler is confused. It is a bad time. But luckily, the more type annotations you add, the better chance there is that you and the compiler can figure things out! So say we change our definition to:
33+
34+```elm
35+incrementNumbers : List Int -> List Int
36+incrementNumbers list =
37+ List.map incrementNumbers list -- STILL HAS BUG
38+```
39+
40+Now we are going to get a pretty normal type error. Hey, you said that each element in the `list` is an `Int` but I cannot feed that into a `List Int -> List Int` function! Something like that.
41+
42+In summary, the root issue is often some small typo, and the best way out is to start adding type annotations on everything!
hints/init.mdnew file+55
@@ -0,0 +1,55 @@
1+
2+# Creating an Elm project
3+
4+The main goal of `elm init` is to get you to this page!
5+
6+It just creates an `elm.json` file and a `src/` directory for your code.
7+
8+
9+## What is `elm.json`?
10+
11+This file describes your project. It lists all of the packages you depend upon, so it will say the particular version of [`elm/core`](https://package.elm-lang.org/packages/elm/core/latest/) and [`elm/html`](https://package.elm-lang.org/packages/elm/html/latest/) that you are using. It makes builds reproducible! You can read a bit more about it [here](https://github.com/elm/compiler/blob/master/docs/elm.json/application.md).
12+
13+You should generally not edit it by hand. It is better to add new dependencies with commands like `elm install elm/http` or `elm install elm/json`.
14+
15+
16+## What goes in `src/`?
17+
18+This is where all of your Elm files live. It is best to start with a file called `src/Main.elm`. As you work through [the official guide](https://guide.elm-lang.org/), you can put the code examples in that `src/Main.elm` file.
19+
20+
21+## How do I compile it?
22+
23+Run `elm reactor` in your project. Now you can go to [`http://localhost:8000`](http://localhost:8000) and browse through all the files in your project. If you navigate to `.elm` files, it will compile them for you!
24+
25+If you want to do things more manually, you can run `elm make src/Main.elm` and it will produce an `index.html` file that you can look at in your browser.
26+
27+
28+## How do I structure my directories?
29+
30+Many folks get anxious about their project structure. “If I get it wrong, I am doomed!” This anxiety makes sense in languages where refactoring is risky, but Elm is not one of those languages!
31+
32+So we recommend that newcomers staying in one file until you get into the 600 to 1000 range. Push out of your comfort zone. Having the experience of being fine in large files will help you understand the boundaries in Elm, rather than just defaulting to the boundaries you learned in another language.
33+
34+The talk [The Life of a File](https://youtu.be/XpDsk374LDE) gets into this a lot more. The advice about building modules around a specific [custom type](https://guide.elm-lang.org/types/custom_types.html) is particularly important! You will see that emphasized a lot as you work through the official guide.
35+
36+
37+## How do I write tests?
38+
39+Elm will catch a bunch of errors statically, and I think it is worth skipping tests at first to get a feeling for when tests will actually help you _in Elm_.
40+
41+From there, we have a great testing package called [`elm-explorations/test`](https://github.com/elm-explorations/test) that can help you out! It is particularly helpful for teams working on a large codebase. When you are editing code you have never seen before, tests can capture additional details and constraints that are not otherwise apparent!
42+
43+
44+## How do I start fancier projects?
45+
46+I wanted `elm init` to generate as little code as possible. It is mainly meant to get you to this page! If you would like a more elaborate starting point, I recommend starting projects with commands like these:
47+
48+```bash
49+git clone https://github.com/evancz/elm-todomvc.git
50+git clone https://github.com/rtfeldman/elm-spa-example.git
51+```
52+
53+The idea is that Elm projects should be so simple that nobody needs a tool to generate a bunch of stuff. This also captures the fact that project structure _should_ evolve organically as your application develops, never ending up exactly the same as other projects.
54+
55+But if you have something particular you want, I recommend creating your own starter recipe and using `git clone` when you start new projects. That way (1) you can get exactly what you want and (2) we do not end up with a complex `elm init` that ends up being confusing for beginners!
hints/missing-patterns.mdnew file+139
@@ -0,0 +1,139 @@
1+
2+# Hints for Missing Patterns
3+
4+Elm checks to make sure that all possible inputs to a function or `case` are handled. This gives us the guarantee that no Elm code is ever going to crash because data had an unexpected shape.
5+
6+There are a couple techniques for making this work for you in every scenario.
7+
8+
9+## The danger of wildcard patterns
10+
11+A common scenario is that you want to add a tag to a custom type that is used in a bunch of places. For example, maybe you are working different variations of users in a chat room:
12+
13+```elm
14+type User
15+ = Regular String Int
16+ | Anonymous
17+
18+toName : User -> String
19+toName user =
20+ case user of
21+ Regular name _ ->
22+ name
23+
24+ _ ->
25+ "anonymous"
26+```
27+
28+Notice the wildcard pattern in `toName`. This will hurt us! Say we add a `Visitor String` variant to `User` at some point. Now we have a bug that visitor names are reported as `"anonymous"`, and the compiler cannot help us!
29+
30+So instead, it is better to explicitly list all possible variants, like this:
31+
32+```elm
33+type User
34+ = Regular String Int
35+ | Visitor String
36+ | Anonymous
37+
38+toName : User -> String
39+toName user =
40+ case user of
41+ Regular name _ ->
42+ name
43+
44+ Anonymous ->
45+ "anonymous"
46+```
47+
48+Now the compiler will say "hey, what should `toName` do when it sees a `Visitor`?" This is a tiny bit of extra work, but it is very worth it!
49+
50+
51+## I want to go fast!
52+
53+Imagine that the `User` type appears in 20 or 30 functions across your project. When we add a `Visitor` variant, the compiler points out all the places that need to be updated. That is very convenient, but in a big project, maybe you want to get through it extra quickly.
54+
55+In that case, it can be helpful to use [`Debug.todo`](https://package.elm-lang.org/packages/elm-lang/core/latest/Debug#todo) to leave some code incomplete:
56+
57+```elm
58+type User
59+ = Regular String Int
60+ | Visitor String
61+ | Anonymous
62+
63+toName : User -> String
64+toName user =
65+ case user of
66+ Regular name _ ->
67+ name
68+
69+ Visitor _ ->
70+ Debug.todo "give the visitor name"
71+
72+ Anonymous ->
73+ "anonymous"
74+
75+-- and maybe a bunch of other things
76+```
77+
78+In this case it is easier to just write the implementation, but the point is that on more complex functions, you can put things off a bit.
79+
80+The Elm compiler is actually aware of `Debug.todo` so when it sees it in a `case` like this, it will crash with a bunch of helpful information. It will tell you:
81+
82+ 1. The name of the module that contains the code.
83+ 2. The line numbers of the `case` containing the TODO.
84+ 3. The particular value that led to this TODO.
85+
86+From that information you have a pretty good idea of what went wrong and can go fix it.
87+
88+I tend to use `Debug.todo` as the message when my goal is to go quick because it makes it easy to go and find all remaining todos in my code before a release.
89+
90+
91+## A list that definitely is not empty
92+
93+This can come up from time to time, but Elm **will not** let you write code like this:
94+
95+```elm
96+last : List a -> a
97+last list =
98+ case list of
99+ [x] ->
100+ x
101+
102+ _ :: rest ->
103+ last rest
104+```
105+
106+This is no good. It does not handle the empty list. There are two ways to handle this. One is to make the function return a `Maybe` like this:
107+
108+```elm
109+last : List a -> Maybe a
110+last list =
111+ case list of
112+ [] ->
113+ Nothing
114+
115+ [x] ->
116+ Just x
117+
118+ _ :: rest ->
119+ last rest
120+```
121+
122+This is nice because it lets users know that there might be a failure, so they can recover from it however they want.
123+
124+The other option is to “unroll the list” one level to ensure that no one can ever provide an empty list in the first place:
125+
126+```elm
127+last : a -> List a -> a
128+last first rest =
129+ case rest of
130+ [] ->
131+ first
132+
133+ newFirst :: newRest ->
134+ last newFirst newRest
135+```
136+
137+By demanding the first element of the list as an argument, it becomes impossible to call this function if you have an empty list!
138+
139+This “unroll the list” trick is quite useful. I recommend using it directly, not through some external library. It is nothing special. Just a useful idea!
hints/optimize.mdnew file+59
@@ -0,0 +1,59 @@
1+
2+# How to optimize Elm code
3+
4+When you are serving a website, there are two kinds of optimizations you want to do:
5+
6+1. **Asset Size** &mdash; How can we send as few bits as possible?
7+2. **Performance** &mdash; How can those bits run as quickly as possible?
8+
9+It turns out that Elm does really well on both! We have [very small assets](https://elm-lang.org/news/small-assets-without-the-headache) and [very fast code](https://elm-lang.org/news/blazing-fast-html-round-two) when compared to the popular alternatives.
10+
11+Okay, but how do we get those numbers?
12+
13+
14+## Instructions
15+
16+Step one is to compile with the `--optimize` flag. This does things like shortening record field names and unboxing values.
17+
18+Step two is to call `uglifyjs` with a bunch of special flags. The flags unlock optimizations that are unreliable in normal JS code, but because Elm does not have side-effects, they work fine for us!
19+
20+Putting those together, here is how I would optimize `src/Main.elm` with two terminal commands:
21+
22+```bash
23+elm make src/Main.elm --optimize --output=elm.js
24+uglifyjs elm.js --compress "pure_funcs=[F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9],pure_getters,keep_fargs=false,unsafe_comps,unsafe" | uglifyjs --mangle --output=elm.min.js
25+```
26+
27+After this you will have an `elm.js` and a significantly smaller `elm.min.js` file!
28+
29+**Note 1:** `uglifyjs` is called twice there. First to `--compress` and second to `--mangle`. This is necessary! Otherwise `uglifyjs` will ignore our `pure_funcs` flag.
30+
31+**Note 2:** If the `uglifyjs` command is not available in your terminal, you can run the command `npm install uglify-js --global` to download it. You probably already have `npm` from getting `elm repl` working, but if not, it is bundled with [nodejs](https://nodejs.org/).
32+
33+## Scripts
34+
35+It is hard to remember all that, so it is probably a good idea to write a script that does it.
36+
37+I would maybe want to run `./optimize.sh src/Main.elm` and get out `elm.js` and `elm.min.js`, so on Mac or Linux, I would make a script called `optimize.sh` like this:
38+
39+```bash
40+#!/bin/sh
41+
42+set -e
43+
44+js="elm.js"
45+min="elm.min.js"
46+
47+elm make --optimize --output=$js $@
48+
49+uglifyjs $js --compress "pure_funcs=[F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9],pure_getters,keep_fargs=false,unsafe_comps,unsafe" | uglifyjs --mangle --output=$min
50+
51+echo "Initial size: $(cat $js | wc -c) bytes ($js)"
52+echo "Minified size:$(cat $min | wc -c) bytes ($min)"
53+echo "Gzipped size: $(cat $min | gzip -c | wc -c) bytes"
54+```
55+
56+It also prints out all the asset sizes for you! Your server should be configured to gzip the assets it sends, so the last line is telling you how many bytes would _actually_ get sent to the user.
57+
58+Again, the important commands are `elm` and `uglifyjs` which work on any platform, so it should not be too tough to do something similar on Windows.
59+
hints/port-modules.mdnew file+32
@@ -0,0 +1,32 @@
1+
2+# No Ports in Packages
3+
4+The package ecosystem is one of the most important parts of Elm. Right now, our ecosystem has some compelling benefits:
5+
6+ - There are many obvious default packages that work well.
7+ - Adding dependencies cannot introduce runtime exceptions.
8+ - Patch changes cannot lead to surprise build failures.
9+
10+These are really important factors if you want to *quickly* create *reliable* applications. The Elm community thinks this is valuable.
11+
12+Other communities think that the *number* of packages is a better measure of ecosystem health. That is a fine metric to use, but it is not the one we use for Elm. We would rather have 50 great packages than 100k packages of wildly varying quality.
13+
14+
15+## So what about ports?
16+
17+Imagine you install a new package that claims to support `localStorage`. You get it set up, working through any compile errors. You run it, but it does not seem to work! After trying to figure it out for hours, you realize there is some poorly documented `port` to hook up...
18+
19+Okay, now you need to hook up some JavaScript code. Is that JS file in the Elm package? Or is it on `npm`? Wait, what version on `npm` though? And is this patch version going to work as well? Also, how does this file fit into my build process? And assuming we get through all that, maybe the `port` has the same name as one of the ports in your project. Or it clashes with a `port` name in another package.
20+
21+**Suddenly adding dependencies is much more complicated and risky!** An experienced developer would always check for ports up front, spending a bunch of time manually classifying unacceptable packages. Most people would not know to do that and learn all the pitfalls through personal experience, ultimately spending even *more* time than the person who defensively checks to avoid these issues.
22+
23+So “ports in packages” would impose an enormous cost on application developers, and in the end, we would have a less reliable package ecosystem overall.
24+
25+
26+## Conclusion
27+
28+Our wager with the Elm package ecosystem is that it is better to get a package *right* than to get it *right now*. So while we could use “ports in packages” as a way to get twenty `localStorage` packages of varying quality *right now*, we are choosing not to go that route. Instead we ask that developers use ports directly in their application code, getting the same result a different way.
29+
30+Now this may not be the right choice for your particular project, and that is okay! We will be expanding our core libraries over time, as explained [here](https://github.com/elm-lang/projects/blob/master/roadmap.md#where-is-the-localstorage-package), and we hope you will circle back later to see if Elm has grown into a better fit!
31+
32+If you have more questions about this choice or what it means for your application, please come ask in [the Elm slack](http://elmlang.herokuapp.com/). Folks are friendly and happy to help out! Chances are that a `port` in your application will work great for your case once you learn more about how they are meant to be used.
hints/ports.mdnew file+2
@@ -0,0 +1,2 @@
1+
2+# Ports
hints/recursive-alias.mdnew file+162
@@ -0,0 +1,162 @@
1+
2+# Hints for Recursive Type Aliases
3+
4+At the root of this issue is the distinction between a `type` and a `type alias`.
5+
6+
7+## What is a type alias?
8+
9+When you create a type alias, you are just creating a shorthand to refer to an existing type. So when you say the following:
10+
11+```elm
12+type alias Time = Float
13+
14+type alias Degree = Float
15+
16+type alias Weight = Float
17+```
18+
19+You have not created any *new* types, you just made some alternate names for `Float`. You can write down things like this and it'll work fine:
20+
21+```elm
22+add : Time -> Degree -> Weight
23+add time degree =
24+ time + degree
25+```
26+
27+This is kind of a weird way to use type aliases though. The typical usage would be for records, where you do not want to write out the whole thing every time. Stuff like this:
28+
29+```elm
30+type alias Person =
31+ { name : String
32+ , age : Int
33+ , height : Float
34+ }
35+```
36+
37+It is much easier to write down `Person` in a type, and then it will just expand out to the underlying type when the compiler checks the program.
38+
39+
40+## Recursive type aliases?
41+
42+Okay, so lets say you have some type that may contain itself. In Elm, a common example of this is a comment that might have subcomments:
43+
44+```elm
45+type alias Comment =
46+ { message : String
47+ , upvotes : Int
48+ , downvotes : Int
49+ , responses : List Comment
50+ }
51+```
52+
53+Now remember that type *aliases* are just alternate names for the real type. So to make `Comment` into a concrete type, the compiler would start expanding it out.
54+
55+```elm
56+ { message : String
57+ , upvotes : Int
58+ , downvotes : Int
59+ , responses :
60+ List
61+ { message : String
62+ , upvotes : Int
63+ , downvotes : Int
64+ , responses :
65+ List
66+ { message : String
67+ , upvotes : Int
68+ , downvotes : Int
69+ , responses : List ...
70+ }
71+ }
72+ }
73+```
74+
75+The compiler cannot deal with values like this. It would just keep expanding forever.
76+
77+
78+## Recursive types!
79+
80+In cases where you want a recursive type, you need to actually create a brand new type. This is what the `type` keyword is for. A simple example of this can be seen when defining a linked list:
81+
82+```elm
83+type List
84+ = Empty
85+ | Node Int List
86+```
87+
88+No matter what, the type of `Node n xs` is going to be `List`. There is no expansion to be done. This means you can represent recursive structures with types that do not explode into infinity.
89+
90+So let's return to wanting to represent a `Comment` that may have responses. There are a couple ways to do this:
91+
92+
93+### Obvious, but kind of annoying
94+
95+```elm
96+type Comment =
97+ Comment
98+ { message : String
99+ , upvotes : Int
100+ , downvotes : Int
101+ , responses : List Comment
102+ }
103+```
104+
105+Now lets say you want to register an upvote on a comment:
106+
107+```elm
108+upvote : Comment -> Comment
109+upvote (Comment comment) =
110+ Comment { comment | upvotes = 1 + comment.upvotes }
111+```
112+
113+It is kind of annoying that we now have to unwrap and wrap the record to do anything with it.
114+
115+
116+### Less obvious, but nicer
117+
118+```elm
119+type alias Comment =
120+ { message : String
121+ , upvotes : Int
122+ , downvotes : Int
123+ , responses : Responses
124+ }
125+
126+type Responses = Responses (List Comment)
127+```
128+
129+In this world, we introduce the `Responses` type to capture the recursion, but `Comment` is still an alias for a record. This means the `upvote` function looks nice again:
130+
131+```elm
132+upvote : Comment -> Comment
133+upvote comment =
134+ { comment | upvotes = 1 + comment.upvotes }
135+```
136+
137+So rather than having to unwrap a `Comment` to do *anything* to it, you only have to do some unwrapping in the cases where you are doing something recursive. In practice, this means you will do less unwrapping which is nice.
138+
139+
140+## Mutually recursive type aliases
141+
142+It is also possible to build type aliases that are *mutually* recursive. That might be something like this:
143+
144+```elm
145+type alias Comment =
146+ { message : String
147+ , upvotes : Int
148+ , downvotes : Int
149+ , responses : Responses
150+ }
151+
152+type alias Responses =
153+ { sortBy : SortBy
154+ , responses : List Comment
155+ }
156+
157+type SortBy = Time | Score | MostResponses
158+```
159+
160+When you try to expand `Comment` you have to expand `Responses` which needs to expand `Comment` which needs to expand `Responses`, etc.
161+
162+So this is just a fancy case of a self-recursive type alias. The solution is the same. Somewhere in that cycle, you need to define an actual `type` to end the infinite expansion.
hints/repl.mdnew file+73
@@ -0,0 +1,73 @@
1+
2+# REPL
3+
4+The REPL lets you interact with Elm values and functions in your terminal.
5+
6+
7+## Use
8+
9+You can type in expressions, definitions, custom types, and module imports using normal Elm syntax.
10+
11+```elm
12+> 1 + 1
13+2 : number
14+
15+> "hello" ++ "world"
16+"helloworld" : String
17+```
18+
19+The same can be done with definitions and custom types:
20+
21+```elm
22+> fortyTwo = 42
23+42 : number
24+
25+> increment n = n + 1
26+<function> : number -> number
27+
28+> increment 41
29+42 : number
30+
31+> factorial n =
32+| if n < 1 then
33+| 1
34+| else
35+| n * factorial (n-1)
36+|
37+<function> : number -> number
38+
39+> factorial 5
40+120 : number
41+
42+> type User
43+| = Regular String
44+| | Visitor String
45+|
46+
47+> case Regular "Tom" of
48+| Regular name -> "Hey again!"
49+| Visitor name -> "Nice to meet you!"
50+|
51+"Hey again!" : String
52+```
53+
54+When you run `elm repl` in a project with an [`elm.json`](https://github.com/elm/compiler/blob/master/docs/elm.json/application.md) file, you can import any module available in the project. So if your project has an `elm/html` dependency, you could say:
55+
56+```elm
57+> import Html exposing (Html)
58+
59+> Html.text "hello"
60+<internals> : Html msg
61+
62+> Html.text
63+<function> : String -> Html msg
64+```
65+
66+If you create a module in your project named `MyThing` in your project, you can say `import MyThing` in the REPL as well. Any module that is accessible in your project should be accessible in the REPL.
67+
68+
69+## Exit
70+
71+To exit the REPL, you can type `:exit`.
72+
73+You can also press `ctrl-d` or `ctrl-c` on some platforms.
hints/shadowing.mdnew file+70
@@ -0,0 +1,70 @@
1+
2+# Variable Shadowing
3+
4+Variable shadowing is when you define the same variable name twice in an ambiguous way. Here is a pretty reasonable use of shadowing:
5+
6+```elm
7+viewName : Maybe String -> Html msg
8+viewName name =
9+ case name of
10+ Nothing ->
11+ ...
12+
13+ Just name ->
14+ ...
15+```
16+
17+I define a `name` with type `Maybe String` and then in that second branch, I define a `name` that is a `String`. Now that there are two `name` values, it is not 100% obvious which one you want in that second branch.
18+
19+Most linters produce warnings on variable shadowing, so Elm makes “best practices” the default. Just rename the first one to `maybeName` and move on.
20+
21+This choice is relatively uncommon in programming languages though, so I want to provide the reasoning behind it.
22+
23+
24+## The Cost of Shadowing
25+
26+The code snippet from above is the best case scenario for variable shadowing. It is pretty clear really. But that is because it is a fake example. It does not even compile.
27+
28+In a large module that is evolving over time, this is going to cause bugs in a very predictable way. You will have two definitions, separated by hundreds of lines. For example:
29+
30+```elm
31+name : String
32+name =
33+ "Tom"
34+
35+-- hundreds of lines
36+
37+viewName : String -> Html msg
38+viewName name =
39+ ... name ... name ... name ...
40+```
41+
42+Okay, so the `viewName` function has an argument `name` and it uses it three times. Maybe the `viewName` function is 50 lines long in total, so those uses are not totally easy to see. This is fine so far, but say your colleague comes along five months later and wants to support first and last names. They refactor the code like this:
43+
44+```elm
45+viewName : String -> String -> Html msg
46+viewName firstName lastName =
47+ ... name ... name ... name ...
48+```
49+
50+The code compiles, but it does not work as intended. They forgot to change all the uses of `name`, and because it shadows the top-level `name` value, it always shows up as `"Tom"`. It is a simple mistake, but it is always the last thing I think of.
51+
52+> Is the data being fetched properly? Let me log all of the JSON requests. Maybe the JSON decoders are messed up? Hmm. Maybe someone is transforming the name in a bad way at some point? Let me check my `update` code.
53+
54+Basically, a bunch of time gets wasted on something that could easily be detected by the compiler. But this bug is rare, right?
55+
56+
57+## Aggregate Cost
58+
59+Thinking of a unique and helpful name takes some extra time. Maybe 30 seconds. But it means that:
60+
61+ 1. Your code is easier to read and understand later on. So you spend 30 seconds once `O(1)` rather than spending 10 seconds each time someone reads that code in the future `O(n)`.
62+
63+ 2. The tricky shadowing bug described above is impossible. Say there is a 5% chance that any given edit produces a shadowing bug, and that resolving that shadowing bug takes one hour. That means the expected time for each edit increases by three minutes.
64+
65+If you are still skeptical, I encourage you can play around with the number of edits, time costs, and probabilities here. When shadowing is not allowed, the resulting overhead for the entire lifetime of the code is the 30 seconds it takes to pick a better name, so that is what you need to beat!
66+
67+
68+## Summary
69+
70+Without shadowing, the code easier to read and folks spend less time on pointless debugging. The net outcome is that folks have more time to make something wonderful with Elm!
hints/tuples.mdnew file+19
@@ -0,0 +1,19 @@
1+
2+# From Tuples to Records
3+
4+The largest tuple possible in Elm has three entries. Once you get to four, it is best to make a record with named entries.
5+
6+For example, it is _conceivable_ to represent a rectangle as four numbers like `(10,10,100,100)` but it would be more self-documenting to use a record like this:
7+
8+```elm
9+type alias Rectangle =
10+ { x : Float
11+ , y : Float
12+ , width : Float
13+ , height : Float
14+ }
15+```
16+
17+Now it is clear that the dimensions should be `Float` values. It is also clear that we are not using the convention of specifying the top-left and bottom-right corners. It could be clearer about whether the `x` and `y` is the point in the top-left or in the middle though!
18+
19+Anyway, using records like this also gives you access to syntax like `rect.x`, `.x`, and `{ rect | x = 40 }`. It is not clear how to design features like that for arbitrarily sized tuples, so we did not. We already have a way, and it is more self-documenting!
hints/type-annotations.mdnew file+62
@@ -0,0 +1,62 @@
1+
2+# Hints for Type Annotation Problems
3+
4+At the root of this kind of issue is always the fact that a type annotation in your code does not match the corresponding definition. Now that may mean that the type annotation is "wrong" or it may mean that the definition is "wrong". The compiler cannot figure out your intent, only that there is some mismatch.
5+
6+This document is going to outline the various things that can go wrong and show some examples.
7+
8+
9+## Annotation vs. Definition
10+
11+The most common issue is with user-defined type variables that are too general. So lets say you have defined a function like this:
12+
13+```elm
14+addPair : (a, a) -> a
15+addPair (x, y) =
16+ x + y
17+```
18+
19+The issue is that the type annotation is saying "I will accept a tuple containing literally *anything*" but the definition is using `(+)` which requires things to be numbers. So the compiler is going to infer that the true type of the definition is this:
20+
21+```elm
22+addPair : (number, number) -> number
23+```
24+
25+So you will probably see an error saying "I cannot match `a` with `number`" which is essentially saying, you are trying to provide a type annotation that is **too general**. You are saying `addPair` accepts anything, but in fact, it can only handle numbers.
26+
27+In cases like this, you want to go with whatever the compiler inferred. It is good at figuring this kind of stuff out ;)
28+
29+
30+## Annotation vs. Itself
31+
32+It is also possible to have a type annotation that clashes with itself. This is probably more rare, but someone will run into it eventually. Let's use another version of `addPair` with problems:
33+
34+```elm
35+addPair : (Int, Int) -> number
36+addPair (x, y) =
37+ x + y
38+```
39+
40+In this case the annotation says we should get a `number` out, but because we were specific about the inputs being `Int`, the output should also be an `Int`.
41+
42+
43+## Annotation vs. Internal Annotation
44+
45+A quite tricky case is when an outer type annotation clashes with an inner type annotation. Here is an example of this:
46+
47+```elm
48+filter : (a -> Bool) -> List a -> List a
49+filter isOkay list =
50+ let
51+ keepIfOkay : a -> Maybe a
52+ keepIfOkay x =
53+ if isOkay x then Just x else Nothing
54+ in
55+ List.filterMap keepIfOkay list
56+```
57+
58+This case is very unfortunate because all the type annotations are correct, but there is a detail of how type inference works right now that **user-defined type variables are not shared between annotations**. This can lead to probably the worst type error messages we have because the problem here is that `a` in the outer annotation does not equal `a` in the inner annotation.
59+
60+For now the best route is to leave off the inner annotation. It is unfortunate, and hopefully we will be able to do a nicer thing in future releases.
61+
62+"""
hints/types-vs-type-aliases.mdnew file+1
@@ -0,0 +1 @@
1+# Types vs Type Aliases