From 3c25e2831ed826c154de7e6783654011f607a105 Mon Sep 17 00:00:00 2001
From: Matthijs Blom <19817960+MatthijsBlom@users.noreply.github.com>
Date: Sun, 18 Dec 2022 20:27:27 +0100
Subject: [PATCH] Add Lists concept
---
concepts/lists/.meta/config.json | 5 +
concepts/lists/about.md.tpl | 3 +
concepts/lists/introduction.md | 182 +++++++++++++++++++++++++++++++
concepts/lists/links.json | 26 +++++
config.json | 5 +
5 files changed, 221 insertions(+)
create mode 100644 concepts/lists/.meta/config.json
create mode 100644 concepts/lists/about.md.tpl
create mode 100644 concepts/lists/introduction.md
create mode 100644 concepts/lists/links.json
diff --git a/concepts/lists/.meta/config.json b/concepts/lists/.meta/config.json
new file mode 100644
index 000000000..ff9086902
--- /dev/null
+++ b/concepts/lists/.meta/config.json
@@ -0,0 +1,5 @@
+{
+ "authors": ["MatthijsBlom"],
+ "contributors": [],
+ "blurb": "Lists in Haskell are homogenous lazy linked lists. Depending on your needs, they can serve as data containers, generators, or streams. In this concept node you'll learn about list literal syntax, types of lists, and where to find documentation on functions that operate on lists."
+}
diff --git a/concepts/lists/about.md.tpl b/concepts/lists/about.md.tpl
new file mode 100644
index 000000000..63fda19ae
--- /dev/null
+++ b/concepts/lists/about.md.tpl
@@ -0,0 +1,3 @@
+# About
+
+%{concept:lists}
diff --git a/concepts/lists/introduction.md b/concepts/lists/introduction.md
new file mode 100644
index 000000000..682dbc696
--- /dev/null
+++ b/concepts/lists/introduction.md
@@ -0,0 +1,182 @@
+# Introduction
+
+The **list** might well be Haskell's most important data structure.
+
+
+## Syntax
+
+Here are some examples of lists.
+
+```haskell
+someIntegers = [3, -1, 4, 1, 5] -- a list of integers
+someDoubles = [9.2, 6.53, 5.89] -- a list of decimal numbers
+someBools = [True, False] -- a list of booleans
+someChars = ['H', 'i', '!'] -- a list of characters
+someFunctions = [isUpper, isSpace] -- a list of functions
+emptyList = [] -- an empty list
+```
+~~~~exercism/advanced
+The above expressions are called **list literals**, because just like number literals (`9`, `1.6`) the syntax is special.
+Less syntactically special ways of building lists exist.
+We'll get to those when we learn about **algebraic data types** and **pattern matching**.
+~~~~
+
+For some types of elements, a shorthand for ranges is available:
+
+```haskell
+someOddNumbers = [9, 11 .. 17] -- [9, 11, 13, 15, 17]
+firstHalfOfAlphabet = ['a' .. 'm'] -- "abcdefghijklm"
+everySecondLetter = ['b', 'd' .. 'z'] -- "bdfhjlnprtvxz"
+multiplesOf7 = [0, 7 ..] -- infinite list [0, 7, 14, 21, …]
+positiveIntegers = [1 ..] -- infinite list [1, 2, 3, …]
+```
+
+~~~~exercism/caution
+Do not ask your computer to print an infinite list, or to otherwise process all its elements.
+Even though much faster than you, it'll never finish.
+
+Asking for a finite amount of work is fine though:
+
+```haskell
+ghci> take 5 [0, 3 ..]
+[0,3,6,9,12]
+```
+~~~~
+
+
+## List types
+
+In Haskell, lists are **homogenous**.
+This means that all elements of a list have the same type.
+When you try to put elements of different types into the same list, you will get a type error.
+
+```haskell
+heterogenousList = [True, 'X']
+-- […]: error:
+-- • Couldn't match expected type ‘Bool’ with actual type ‘Char’
+-- • In the expression: 'X'
+```
+
+Because elements's types are always the same, it makes sense to speak of _lists of integers_, _lists of booleans_, _lists of functions_, etc.
+Indeed, all of these kinds of lists have their own types!
+
+```haskell
+ghci> :type someBools
+someBools :: [Bool] -- the type of lists of booleans
+ghci> :type someChars
+someChars :: [Char] -- the type of lists of characters
+ghci> :type someFunctions
+someFunctions :: [Char -> Bool] -- the type of lists of functions
+```
+
+~~~~exercism/note
+As you can see, the `[…]` syntax is slightly overloaded: it can denote both values and types.
+It is however never truly ambiguous, because of strictly distinguished syntactical contexts:
+
+```haskell
+name :: {- only types here -}
+name = {- only values here -}
+```
+
+To add to that,
+
+- `[a, b, c]` and `[]` are values
+- `[6]`, `[True]`, `[[]]` are values, because `6`, `True`, `[]` are all values
+- `[Bool]` is a type, because `Bool` is a type
+- `[a]` is a type when `a` is a type variable, and a value otherwise.
+~~~~
+
+~~~~exercism/advanced
+The family of types of lists has a name: `[]`.
+It is, strictly speaking, not a type itself.
+Instead, it is a _type constructor_, or _parametric type_.
+We'll get to what this means exactly in subsequent concept nodes.
+
+When you hear people talk about «the `[]` type», most likely they mean this family of types rather than any specific type.
+~~~~
+
+
+## Lists representing text: `String`
+
+Haskell does not have a built-in data type for representing text.
+Instead, by default it represents text as lists of characters.
+
+```haskell
+['H', 'i', '!'] -- a greeting: a list of characters
+```
+
+Lists of characters are syntactically unwieldy, so Haskell features some handy syntactic sugar:
+
+```haskell
+ghci> ['H', 'i', '!'] == "Hi!"
+True
+ghci> "" == []
+True
+```
+
+~~~~exercism/note
+In contrast to in some other languages, in Haskell single quotes (`'`) and double quotes (`"`) are not interchangeable.
+Single quotes denote `Char`acters, whereas double quotes denote `String`s (i.e. lists of characters).
+
+```haskell
+ghci> :type 'a'
+'a' :: Char
+ghci> :type "a"
+"a" :: String
+```
+~~~~
+
+Also for convenience, Haskell provides the name `String`, which is a _type synonym_ of `[Char]`.
+Two names for exactly the same type, they are entirely interchangeable:
+
+```haskell
+ghci> (['H', 'i', '!'] :: String) == ("Hi!" :: [Char])
+True
+```
+
+
+## Working with lists
+
+Owing to lists' ubiquitousness, lots of utilities for working with them are present in the standard library.
+
+The very most important functions you'll find in [the `Prelude`][prelude].
+Other much-used functions live in [the `Data.List` module][data.list].
+Be sure to have a good look-around!
+
+Functions that are provided by the `Prelude` you do not need to import, as the `Prelude` itself is implicitly imported by default.
+Functions from `Data.List` however you do need to explicitly import.
+
+~~~~exercism/advanced
+Haskell's lists are singly-linked lists.
+This has consequences in performance characteristics of list operations.
+For example, `length` takes time proportional to list length, `!!` (index) takes time linear in the index, and `++` (append) takes time proportional to (only!) the length of the left operand.
+~~~~
+
+
+### How to interpret `Foldable` constraints
+
+In many places in the documentation you'll find functions with signatures mentioning `Foldable`, e.g.
+
+```haskell
+length :: Foldable t => t a -> Int
+```
+
+We'll get to what this means exactly later.
+For now, you can read all such signatures as if they are about lists:
+
+```haskell
+-- 1. remember this name
+-- 👇
+length :: Foldable t => t a -> Int
+-- 👆
+-- 2. replace all occurrences with […]
+-- 👆
+-- 3. remove constraint
+
+-- Result:
+length :: [a] -> Int
+```
+
+
+[data.list]: https://hackage.haskell.org/package/base/docs/Data-List.html "Data.List documentation"
+[prelude]: https://hackage.haskell.org/package/base/docs/Prelude.html "Prelude documentation"
diff --git a/concepts/lists/links.json b/concepts/lists/links.json
new file mode 100644
index 000000000..73f6becf9
--- /dev/null
+++ b/concepts/lists/links.json
@@ -0,0 +1,26 @@
+[
+ {
+ "url": "https://learnyouahaskell.github.io/starting-out.html#an-intro-to-lists",
+ "description": "Learn You A Haskell's introduction to lists"
+ },
+ {
+ "url": "https://learnyouahaskell.github.io/modules.html#data-list",
+ "description": "Learn You A Haskell's tour of `Data.List`"
+ },
+ {
+ "url": "https://en.wikibooks.org/wiki/Haskell/Lists_and_tuples",
+ "description": "Haskell Wikibook's introduction to lists"
+ },
+ {
+ "url": "https://hackage.haskell.org/package/base/docs/Prelude.html",
+ "description": "Prelude documentation"
+ },
+ {
+ "url": "https://hackage.haskell.org/package/base/docs/Data-List.html",
+ "description": "Data.List documentation"
+ },
+ {
+ "url": "https://hoogle.haskell.org/",
+ "description": "Hoogle"
+ }
+]
diff --git a/config.json b/config.json
index 64e7d4d34..da11f1337 100644
--- a/config.json
+++ b/config.json
@@ -1276,6 +1276,11 @@
"slug": "booleans",
"name": "Booleans"
},
+ {
+ "uuid": "67c3fb6a-d519-49d9-a19c-dffdd96ad133",
+ "slug": "lists",
+ "name": "Lists"
+ },
{
"uuid": "ca21a553-6fc1-49be-8f47-730f97330862",
"slug": "pattern-matching-literals",