π "If I miss one day of practice, I notice it. If I miss two days, the critics notice it. If I miss three days, the audience notices it." βΒ Ignacy Jan Paderewski
It's super easy to forget so aim to practice once per week! This is the killer. If I step away from programming for a few weeks, you really feel the rust gathering. This repository is a testing ground for all things Elm, and it's a year-long learning curve to build bigger.
There's plenty of javascript guides out there, so the focus is squarely on a statically typed functional style, good habits, and shaping a good programmer. For a study aid, use Anki flashcards and a clear learning frame.1 They're great for revision, but no substitute for building things.
Elm is great for learning how to engineer.
Start with How To Design Programs and follow that up with Elm. It's better designed, more consistent, with better compiler error messages than Python.
After these two languages you'll have a decent grounding in Computer Science theory, and they're not too academic. I'm rubbish at maths, and am mostly focused on rapid prototyping, so I like to avoid deep academic learning. An artist ships!
π I think the first and most important thing is that you've got to have a goal and a vision βΒ Arnie
Here are my goals:
- Prototyping and validating a business idea
- Writing as little code as possible2
- Teaching beginners (kids and adults)
If I were to start over and learn again, I would:
- Start with HTDP and then Elm
- Learn only a subset of CompSci3 (first two chapters of HTDP, for example)
- Learn the best practices for
httpservers,jsonandRESTAPIs - Learn how to use Ai as a teacher, or for pair-programming
- Learn from a mentor (good habits and what not to do)
- Learn how to frame and structure your learning (fail fast, just build!)
# Initialise an Elm project
elm init
# Install a package
elm install elm/<package>
# Make a HTML file from an Elm one
elm make src/Main.elm
# Compile to javascript file
elm make src/Main.elm --output=app.js
# View in the browser
elm reactor
Why do we need types? It's best illustrated by the old joke ...
A programmer's wife told him "Go to the store and buy milk and if they have eggs, get a dozen." He came back a while later with 12 cartons of milk!
Computer Science is specific, it requires some discipline. If you've used a language like Python before, you'll know that runtime errors can be frustrating and opaque. Elm's compiler solves this problem by inferring (or reading) types. An example below:
shopping : List String
shopping = ["oat milk", "chocolate", "marshmallows"]
checkout : List String -> List Float
checkout list =
List.map (\item -> (priceCheck item)) list
priceCheck : String -> Float
priceCheck item =
if item == "oat milk" then
2.50
else
1.50>> checkout shopping
[2.5, 1.5, 1.5] : List Float
This is where Elm really shines, everything is easy to install and just works! The error messages are clear and helpful, guiding you towards a correct solution, and everything is built in (unlike Python with it's cryptic error messages, None values, and many type checking packages).
checkout ["oat milk", 2, "marshmallows"]-- TYPE MISMATCH ---------------------------------------------------------- REPL
The 2nd element of this list does not match all the previous elements:
16| checkout ["oat milk", 2, "marshmallows"]
^
The 2nd element is a number of type:
number
But all the previous elements in the list are:
String
Hint: Everything in a list must be the same type of value. This way, we never
run into unexpected values partway through a List.map, List.foldl, etc. Read
<https://elm-lang.org/0.19.1/custom-types> to learn how to βmixβ types.
Hint: Try using String.fromInt to convert it to a string?
- Here's how packages are documented
- Elm package design guidelines
π I'm lazy, and rarely test, but it's good practice to.
This mindset will land you in trouble if you're using Python, or any language without strict typing. It's always wise to test your programs as your visitors would use them, as typing only gets you so far. For example, I use Bruno to test my APIs, Hotjar for user testing, manual tests, ocassionally logs, but I generally don't write unit tests. Remember, Elm only checks data types; it won't guarantee your inputs and outputs are what you'd expect.
My goal is prototyping; not testing is a calculated risk, as it (1) speeds up development, and (2) makes life easier for a one-man-show. Forgive me for being a little lax. For mission-critical production projects, finance, larger programs, or working in bigger teams, a lot can go wrong without tests!
It's also helpful to keep an offline library/docs when your wifi breaks (or the internet rots) βΒ there's an app for that.
Here's a wealth of resources for getting started with Elm. Each list is ordered by difficulty (beginners and easiest first). I'd suggest starting with "Beginning Elm" or "Welcome to Elm" to get a taste, move onto the books (or online courses), peruse the helpful talks, check out some real world examples, then it's up to you! You can also run Elm in the browser with Ellie and Elm.run.
- Beginning Elm
- Elm in Action (chapter files in this repo)
- Programming Elm (chapter files on this repo)
- Learn Elm (Elm Craft)
- Official Elm guide
- Elm syntax (quick overview of syntax)
- Elm packages
- Welcome to Elm (nice walkthrough)
- Introduction to Elm (Richard Feldman, tutorial files in this repo)
- Exercism's Elm track
- 7 GUIs for practice
- Elm Workshop (e.g: stopwatch)
- Advanced Elm (Richard Feldman)
- Other courses
- Life of a file
- Teaching Elm to beginners (good for teams)
- Scaling Elm apps
- Making impossible states impossible4
- Make data structures
- From Rails to Elm and Haskell
- How to Elm (this repo, grouped by package type)
- Andy Balaam's Elm examples
- Built with Elm
- Elm Patterns (might be a little outdated)
- Fuzz tests in Elm5
- Sorting comparables (record)
- Elm community FAQs
- Why large records are OK
- Why do I have to use Json decoders?
- What, exactly, is a
Msgfor? (no state please!) - Avoiding import cycles and normalising records
- Hot live reloading with
elm-watch(orelm-live/Parcel/Vite) - Elm land web app framework (or older elm-spa
- Minify and optimise
- Elm Doc Preview (great for offline documentation)
- Everything else (massive list)
- Elm Spa #1 (by @rtfeldman)6
- Elm Spa #2 (Elm Land version)
- Elm Spa #3 (@dwayne's version)
- Elk Herd (by @mzero but it's complex)
Footnotes
-
A learning frame is what you are, and are not, prepared to learn. It's helpful to sketch this out upfront and stick to it. It can change over time, but setting goals and limits keeps you focused. What is it you need to learn, exactly? Here's an example of a learning frame. β©
-
Meaning efficient with my time, not lazy (ok, a little lazy). A simple route with less code and complexity? I'll take it. Take this carousel in Elm, for example. Want to be a great programmer? Go ahead, take your time! Prefer the easy route? Use
scroll-snapwith CSS. It all depends on your vision: I'd rather have more time to pursue other things, keep things simple. β© -
A lot of programming books can be highly academic, and although books like these can be very thorough (and suit some learning styles), for me that was the wrong approach. For example, learning how to code recursively can be intellectually stimulating and it teaches you a lot, but after a certain point, it provides diminishing returns. It's hard to know exactly what you need to learn, but if your goal is to build things, aim for industry knowledge and pragmatic goals, rather than academic ones. Learn the basics well and start building things. You'll learn a lot along the way (with help from mentors), and you can do the heavier academic texts later if you enjoy that kind of thing! β©
-
All (or most) of Richard Feldmans talks β©
-
I'm being a little lazy here. I don't consider myself a "proper" computer scientist (and I don't code that often); more a pragmatic programmer. My goal is prototyping, so I rarely write unit tests. This isn't the correct way, but Elm types give a lot of guarantees: testing the program as a regular user (like a QA) might be enough. If any bugs arise, a visitor can raise a ticket and tests can be written. β©
-
Hopefully these three examples give an understanding of how to do Elm on a larger scale. Elm without a framework like Elm Land needs quite a lot of plumbing, so hopefully there'll be "one way to do it" when Elm Studio eventually comes out. Alas, even that's imperfect as (I've been told) it's not plain old SQL and has abstractions to make the backend work. β©