You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/chapter3.md
+49-46Lines changed: 49 additions & 46 deletions
Original file line number
Diff line number
Diff line change
@@ -18,11 +18,12 @@ The source code for this chapter is contained in the file `src/Data/AddressBook.
18
18
19
19
Here, we import several modules:
20
20
21
+
- The `Prelude` module, which contains a small set of standard definitions and functions. It re-exports many foundational modules from the `purescript-prelude` library.
21
22
- The `Control.Plus` module, which defines the `empty` value.
22
23
- The `Data.List` module, provided by the `lists` package, which can be installed using Spago. It contains a few functions that we will need for working with linked lists.
23
24
- The `Data.Maybe` module, which defines data types and functions for working with optional values.
24
25
25
-
Notice that the imports for these modules are listed explicitly in parentheses. This is generally a good practice, as it helps to avoid conflicting imports.
26
+
Notice that the imports for these modules are listed explicitly in parentheses (except for `Prelude`, which is typically imported as an open import). This is generally a good practice, as it helps to avoid conflicting imports.
26
27
27
28
Assuming you have cloned the book's source code repository, the project for this chapter can be built using Spago, with the following commands:
28
29
@@ -102,18 +103,7 @@ Fields of records can be accessed using a dot, followed by the label of the fiel
102
103
["Functional Programming","JavaScript"]
103
104
```
104
105
105
-
PureScript's functions correspond to JavaScript's functions. The PureScript standard libraries provide plenty of examples of functions, and we will see more in this chapter:
106
-
107
-
```text
108
-
> import Prelude
109
-
> :type flip
110
-
forall a b c. (a -> b -> c) -> b -> a -> c
111
-
112
-
> :type const
113
-
forall a b. a -> b -> a
114
-
```
115
-
116
-
Functions can be defined at the top-level of a file by specifying arguments before the equals sign:
106
+
PureScript's functions correspond to JavaScript's functions. Functions can be defined at the top-level of a file by specifying arguments before the equals sign:
117
107
118
108
```haskell
119
109
add::Int->Int->Int
@@ -136,39 +126,6 @@ Having defined this function in PSCi, we can _apply_ it to its arguments by sepa
136
126
30
137
127
```
138
128
139
-
## Quantified Types
140
-
141
-
In the previous section, we saw the types of some functions defined in the Prelude. For example, the `flip` function had the following type:
142
-
143
-
```text
144
-
> :type flip
145
-
forall a b c. (a -> b -> c) -> b -> a -> c
146
-
```
147
-
148
-
The keyword `forall` here indicates that `flip` has a _universally quantified type_. It means we can substitute any types for `a`, `b`, and `c`, and `flip` will work with those types.
149
-
150
-
For example, we might choose the type `a` to be `Int`, `b` to be `String`, and `c` to be `String`. In that case, we could _specialize_ the type of `flip` to
We don't have to indicate in code that we want to specialize a quantified type – it happens automatically. For example, we can use `flip` as if it had this type already:
157
-
158
-
```text
159
-
> flip (\n s -> show n <> s) "Ten" 10
160
-
161
-
"10Ten"
162
-
```
163
-
164
-
While we can choose any types for `a`, `b`, and `c`, we have to be consistent. The type of function passed to `flip` had to be consistent with the types of the other arguments. That is why we passed the string `"Ten"` as the second argument and the number `10` as the third. It would not work if the arguments were reversed:
165
-
166
-
```text
167
-
> flip (\n s -> show n <> s) 10 "Ten"
168
-
169
-
Could not match type Int with type String
170
-
```
171
-
172
129
## Notes On Indentation
173
130
174
131
PureScript code is _indentation-sensitive_, just like Haskell, but unlike JavaScript. This means that the whitespace in your code is not meaningless, but rather is used to group regions of code, just like curly braces in C-like languages.
@@ -293,6 +250,52 @@ Type
293
250
294
251
PureScript's _kind system_ supports other interesting kinds, which we will see later in the book.
295
252
253
+
## Quantified Types
254
+
255
+
For illustration purposes, let's define a primitive function that takes any two arguments and returns the first one:
256
+
257
+
```text
258
+
> :paste
259
+
… constantlyFirst :: forall a b. a -> b -> a
260
+
… constantlyFirst = \a b -> a
261
+
… ^D
262
+
```
263
+
264
+
> Note that if you use `:type` to ask about the type of `constantlyFirst`, it will be more verbose:
265
+
>
266
+
> ```text
267
+
> : type constantlyFirst
268
+
> forall (a :: Type) (b :: Type). a -> b -> a
269
+
> ```
270
+
>
271
+
> The type signature contains additional kind information, which explicitly notes that `a` and `b` should be concrete types.
272
+
273
+
The keyword `forall` indicates that `constantlyFirst` has a _universally quantified type_. It means we can substitute any types for `a` and `b` – `constantlyFirst` will work with these types.
274
+
275
+
For example, we might choose the type `a` to be `Int` and `b` – `String`. In that case, we can _specialize_ the type of `constantlyFirst` to
276
+
277
+
```text
278
+
Int -> String -> Int
279
+
```
280
+
281
+
We don't have to indicate in code that we want to specialize a quantified type – it happens automatically. For example, we can use `constantlyFirst` as if it had this type already:
282
+
283
+
```text
284
+
> constantlyFirst 3 "ignored"
285
+
286
+
3
287
+
```
288
+
289
+
While we can choose any types for `a` and `b`, the return type of `constantlyFirst` has to be the same as the type of the first argument (because both of them are "tied" to the same `a`):
290
+
291
+
```text
292
+
:type constantlyFirst true "ignored"
293
+
Boolean
294
+
295
+
:type constantlyFirst "keep" 3
296
+
String
297
+
```
298
+
296
299
## Displaying Address Book Entries
297
300
298
301
Let's write our first function, which will render an address book entry as a string. We start by giving the function a type. This is optional, but good practice, since it acts as a form of documentation. In fact, the PureScript compiler will give a warning if a top-level declaration does not contain a type annotation. A type declaration separates the name of a function from its type with the `::` symbol:
0 commit comments