diff --git a/docs/functors-applicative-functors-and-monoids.html b/docs/functors-applicative-functors-and-monoids.html index 3eb5997..214a863 100644 --- a/docs/functors-applicative-functors-and-monoids.html +++ b/docs/functors-applicative-functors-and-monoids.html @@ -167,7 +167,7 @@

Functors, Applicative Functors and Monoids

fmap f (Just x) = Just (f x) fmap f Nothing = Nothing -

We imagine that id plays the role of the f parameter in the implementation. We see that if wee fmap id over Just x, the result will be Just (id x), and because id just returns its parameter, we can deduce that Just (id x) equals Just x. So now we know that if we map id over a Maybe value with a Just value constructor, we get that same value back.

+

We imagine that id plays the role of the f parameter in the implementation. We see that if we fmap id over Just x, the result will be Just (id x), and because id just returns its parameter, we can deduce that Just (id x) equals Just x. So now we know that if we map id over a Maybe value with a Just value constructor, we get that same value back.

Seeing that mapping id over a Nothing value returns the same value is trivial. So from these two equations in the implementation for fmap, we see that the law fmap id = id holds.

justice is blind, but so is my dog

The second law says that composing two functions and then mapping the resulting function over a functor should be the same as first mapping one function over the functor and then mapping the other one. Formally written, that means that fmap (f . g) = fmap f . fmap g. Or to write it in another way, for any functor F, the following should hold: fmap (f . g) F = fmap f (fmap g F).

@@ -512,7 +512,7 @@

Functors, Applicative Functors and Monoids

True

sequenceA [(>4),(<10),odd] creates a function that will take a number and feed it to all of the predicates in [(>4),(<10),odd] and return a list of booleans. It turns a list with the type (Num a) => [a -> Bool] into a function with the type (Num a) => a -> [Bool]. Pretty neat, huh?

-

Because lists are homogenous, all the functions in the list have to be functions of the same type, of course. You can't have a list like [ord, (+3)], because ord takes a character and returns a number, whereas (+3) takes a number and returns a number.

+

Because lists are homogeneous, all the functions in the list have to be functions of the same type, of course. You can't have a list like [ord, (+3)], because ord takes a character and returns a number, whereas (+3) takes a number and returns a number.

When used with [], sequenceA takes a list of lists and returns a list of lists. Hmm, interesting. It actually creates lists that have all possible combinations of their elements. For illustration, here's the above done with sequenceA and then done with a list comprehension:

 ghci> sequenceA [[1,2,3],[4,5,6]]
diff --git a/docs/higher-order-functions.html b/docs/higher-order-functions.html
index f3ef887..d2853ba 100644
--- a/docs/higher-order-functions.html
+++ b/docs/higher-order-functions.html
@@ -325,7 +325,7 @@ 

Higher order functions

sum' = foldl (+) 0

The lambda function (\acc x -> acc + x) is the same as (+). We can omit the xs as the parameter because calling foldl (+) 0 will return a function that takes a list. Generally, if you have a function like foo a = bar b a, you can rewrite it as foo = bar b, because of currying.

-

Anyhoo, let's implement another function with a left fold before moving on to right folds. I'm sure you all know that elem checks whether a value is part of a list so I won't go into that again (whoops, just did!). Let's implement it with a left fold.

+

Anyhow, let's implement another function with a left fold before moving on to right folds. I'm sure you all know that elem checks whether a value is part of a list so I won't go into that again (whoops, just did!). Let's implement it with a left fold.

 elem' :: (Eq a) => a -> [a] -> Bool
 elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys
diff --git a/docs/input-and-output.html b/docs/input-and-output.html
index c5f390d..5e52780 100644
--- a/docs/input-and-output.html
+++ b/docs/input-and-output.html
@@ -1169,7 +1169,7 @@ 

Input and Output

Stop right there, criminal scum! Nobody breaks the law on my watch! Now pay your fine or it's off to jail.

Pure code can throw exceptions, but they can only be caught in the I/O part of our code (when we're inside a do block that goes into main). That's because you don't know when (or if) anything will be evaluated in pure code, because it is lazy and doesn't have a well-defined order of execution, whereas I/O code does.

-

Earlier, we talked about how we should spend as little time as possible in the I/O part of our program. The logic of our program should reside mostly within our pure functions, because their results are dependant only on the parameters that the functions are called with. When dealing with pure functions, you only have to think about what a function returns, because it can't do anything else. This makes your life easier. Even though doing some logic in I/O is necessary (like opening files and the like), it should preferably be kept to a minimum. Pure functions are lazy by default, which means that we don't know when they will be evaluated and that it really shouldn't matter. However, once pure functions start throwing exceptions, it matters when they are evaluated. That's why we can only catch exceptions thrown from pure functions in the I/O part of our code. And that's bad, because we want to keep the I/O part as small as possible. However, if we don't catch them in the I/O part of our code, our program crashes. The solution? Don't mix exceptions and pure code. Take advantage of Haskell's powerful type system and use types like Either and Maybe to represent results that may have failed.

+

Earlier, we talked about how we should spend as little time as possible in the I/O part of our program. The logic of our program should reside mostly within our pure functions, because their results are dependent only on the parameters that the functions are called with. When dealing with pure functions, you only have to think about what a function returns, because it can't do anything else. This makes your life easier. Even though doing some logic in I/O is necessary (like opening files and the like), it should preferably be kept to a minimum. Pure functions are lazy by default, which means that we don't know when they will be evaluated and that it really shouldn't matter. However, once pure functions start throwing exceptions, it matters when they are evaluated. That's why we can only catch exceptions thrown from pure functions in the I/O part of our code. And that's bad, because we want to keep the I/O part as small as possible. However, if we don't catch them in the I/O part of our code, our program crashes. The solution? Don't mix exceptions and pure code. Take advantage of Haskell's powerful type system and use types like Either and Maybe to represent results that may have failed.

That's why we'll just be looking at how to use I/O exceptions for now. I/O exceptions are exceptions that are caused when something goes wrong while we are communicating with the outside world in an I/O action that's part of main. For example, we can try opening a file and then it turns out that the file has been deleted or something. Take a look at this program that opens a file whose name is given to it as a command line argument and tells us how many lines the file has.

 import System.Environment
diff --git a/docs/starting-out.html b/docs/starting-out.html
index e260c1b..ac7870b 100644
--- a/docs/starting-out.html
+++ b/docs/starting-out.html
@@ -212,7 +212,7 @@ 

Starting Out

Much like shopping lists in the real world, lists in Haskell are very useful. It's the most used data structure and it can be used in a multitude of different ways to model and solve a whole bunch of problems. Lists are SO awesome. In this section we'll look at the basics of lists, strings (which are lists) and list comprehensions.

-In Haskell, lists are a homogenous data structure. They store several elements of the same type. That means that we can have a list of integers or a list of characters but we can't have a list that has a few integers and then a few characters. And now, a list! +In Haskell, lists are a homogeneous data structure. They store several elements of the same type. That means that we can have a list of integers or a list of characters but we can't have a list that has a few integers and then a few characters. And now, a list!

 ghci> lostNumbers = [4,8,15,16,23,42]
@@ -479,7 +479,7 @@ 

Starting Out

Tuples

tuples

In some ways, tuples are like lists — they are a way to store several values into a single value. However, there are a few fundamental differences. A list of numbers is a list of numbers. That's its type and it doesn't matter if it has only one number in it or an infinite amount of numbers. Tuples, however, are used when you know exactly how many values you want to combine and its type depends on how many components it has and the types of the components. They are denoted with parentheses and their components are separated by commas.

-

Another key difference is that they don't have to be homogenous. Unlike a list, a tuple can contain a combination of several types.

+

Another key difference is that they don't have to be homogeneous. Unlike a list, a tuple can contain a combination of several types.

Think about how we'd represent a two-dimensional vector in Haskell. One way would be to use a list. That would kind of work. So what if we wanted to put a couple of vectors in a list to represent points of a shape on a two-dimensional plane? We could do something like [[1,2],[8,11],[4,5]]. The problem with that method is that we could also do stuff like [[1,2],[8,11,5],[4,5]], which Haskell has no problem with since it's still a list of lists with numbers, but it kind of doesn't make sense. But a tuple of size two (also called a pair) is its own type, which means that a list can't have a couple of pairs in it and then a triple (a tuple of size three), so let's use that instead. Instead of surrounding the vectors with square brackets, we use parentheses: [(1,2),(8,11),(4,5)]. What if we tried to make a shape like [(1,2),(8,11,5),(4,5)]? Well, we'd get this error:

     • Couldn't match expected type ‘(a, b)’
diff --git a/markdown/source_md/functionally-solving-problems.md b/markdown/source_md/functionally-solving-problems.md
index e109e24..55c107e 100644
--- a/markdown/source_md/functionally-solving-problems.md
+++ b/markdown/source_md/functionally-solving-problems.md
@@ -138,7 +138,7 @@ Also noticed that we added an extra class constraint of `Read a` to the function
 So this declaration means that the result can be of any type that's part of the `Num` and `Read` typeclasses (like `Int`, `Float`, etc.).
 
 For the list of items `["2","3","+"]`, our function will start folding from the left.
-The intial stack will be `[]`.
+The initial stack will be `[]`.
 It will call the folding function with `[]` as the stack (accumulator) and `"2"` as the item.
 Because that item is not an operator, it will be `read` and the added to the beginning of `[]`.
 So the new stack is now `[2]` and the folding function will be called with `[2]` as the stack and `["3"]` as the item, producing a new stack of `[3,2]`.
diff --git a/markdown/source_md/functors-applicative-functors-and-monoids.md b/markdown/source_md/functors-applicative-functors-and-monoids.md
index d93c175..2d2d35c 100644
--- a/markdown/source_md/functors-applicative-functors-and-monoids.md
+++ b/markdown/source_md/functors-applicative-functors-and-monoids.md
@@ -586,7 +586,7 @@ Finally, `Just (3+) <*> Just 5` is carried out, which results in a `Just 8`.
 
 Isn't this awesome?!
 Applicative functors and the applicative style of doing `pure f <*> x <*> y <*> ...` allow us to take a function that expects parameters that aren't necessarily wrapped in functors and use that function to operate on several values that are in functor contexts.
-The function can take as many parameters as we want, because it's always partially applied step by step between occurences of `<*>`.
+The function can take as many parameters as we want, because it's always partially applied step by step between occurrences of `<*>`.
 
 This becomes even more handy and apparent if we consider the fact that `pure f <*> x` equals `fmap f x`.
 This is one of the applicative laws.
@@ -1047,7 +1047,7 @@ True
 It turns a list with the type `(Num a) => [a -> Bool]` into a function with the type `(Num a) => a -> [Bool]`.
 Pretty neat, huh?
 
-Because lists are homogenous, all the functions in the list have to be functions of the same type, of course.
+Because lists are homogeneous, all the functions in the list have to be functions of the same type, of course.
 You can't have a list like `[ord, (+3)]`, because `ord` takes a character and returns a number, whereas `(+3)` takes a number and returns a number.
 
 When used with `[]`, `sequenceA` takes a list of lists and returns a list of lists.
@@ -1578,7 +1578,7 @@ We were able to use the general type of `[a]` (as opposed to specifying `[Int]`
 
 Because `mconcat` has a default implementation, we get it for free when we make something an instance of `Monoid`.
 In the case of the list, `mconcat` turns out to be just `concat`.
-It takes a list of lists and flattens it, because that's the equivalent of doing `++` between all the adjecent lists in a list.
+It takes a list of lists and flattens it, because that's the equivalent of doing `++` between all the adjacent lists in a list.
 
 The monoid laws do indeed hold for the list instance.
 When we have several lists and we `mappend` (or `++`) them together, it doesn't matter which ones we do first, because they're just joined at the ends anyway.
diff --git a/markdown/source_md/higher-order-functions.md b/markdown/source_md/higher-order-functions.md
index d3bcef8..112db76 100644
--- a/markdown/source_md/higher-order-functions.md
+++ b/markdown/source_md/higher-order-functions.md
@@ -617,7 +617,7 @@ The lambda function `(\acc x -> acc + x)` is the same as `(+)`.
 We can omit the `xs` as the parameter because calling `foldl (+) 0` will return a function that takes a list.
 Generally, if you have a function like `foo a = bar b a`, you can rewrite it as `foo = bar b`, because of currying.
 
-Anyhoo, let's implement another function with a left fold before moving on to right folds.
+Anyhow, let's implement another function with a left fold before moving on to right folds.
 I'm sure you all know that `elem` checks whether a value is part of a list so I won't go into that again (whoops, just did!).
 Let's implement it with a left fold.
 
diff --git a/markdown/source_md/input-and-output.md b/markdown/source_md/input-and-output.md
index 6a9b066..52c9bcf 100644
--- a/markdown/source_md/input-and-output.md
+++ b/markdown/source_md/input-and-output.md
@@ -2071,7 +2071,7 @@ Pure code can throw exceptions, but they can only be caught in the I/O part of o
 That's because you don't know when (or if) anything will be evaluated in pure code, because it is lazy and doesn't have a well-defined order of execution, whereas I/O code does.
 
 Earlier, we talked about how we should spend as little time as possible in the I/O part of our program.
-The logic of our program should reside mostly within our pure functions, because their results are dependant only on the parameters that the functions are called with.
+The logic of our program should reside mostly within our pure functions, because their results are dependent only on the parameters that the functions are called with.
 When dealing with pure functions, you only have to think about what a function returns, because it can't do anything else.
 This makes your life easier.
 Even though doing some logic in I/O is necessary (like opening files and the like), it should preferably be kept to a minimum.
diff --git a/markdown/source_md/modules.md b/markdown/source_md/modules.md
index afe40b9..26a9103 100644
--- a/markdown/source_md/modules.md
+++ b/markdown/source_md/modules.md
@@ -1328,7 +1328,7 @@ rectangleArea a b = a * b
 Pretty standard geometry right here.
 There are a few things to take note of though.
 Because a cube is only a special case of a cuboid, we defined its area and volume by treating it as a cuboid whose sides are all of the same length.
-We also defined a helper function called `rectangleArea`, which calculates a rectangle's area based on the lenghts of its sides.
+We also defined a helper function called `rectangleArea`, which calculates a rectangle's area based on the lengths of its sides.
 It's rather trivial because it's just multiplication.
 Notice that we used it in our functions in the module (namely `cuboidArea` and `cuboidVolume`) but we didn't export it!
 Because we want our module to just present functions for dealing with three-dimensional objects, we used `rectangleArea` but we didn't export it.
diff --git a/markdown/source_md/starting-out.md b/markdown/source_md/starting-out.md
index 0bdc97f..b149c3e 100644
--- a/markdown/source_md/starting-out.md
+++ b/markdown/source_md/starting-out.md
@@ -286,7 +286,7 @@ It's the most used data structure and it can be used in a multitude of different
 Lists are SO awesome.
 In this section we'll look at the basics of lists, strings (which are lists) and list comprehensions.
 
-In Haskell, lists are a **homogenous** data structure.
+In Haskell, lists are a **homogeneous** data structure.
 They store several elements of the same type.
 That means that we can have a list of integers or a list of characters but we can't have a list that has a few integers and then a few characters.
 And now, a list!
@@ -771,7 +771,7 @@ That's its type and it doesn't matter if it has only one number in it or an infi
 Tuples, however, are used when you know exactly how many values you want to combine and its type depends on how many components it has and the types of the components.
 They are denoted with parentheses and their components are separated by commas.
 
-Another key difference is that they don't have to be homogenous.
+Another key difference is that they don't have to be homogeneous.
 Unlike a list, a tuple can contain a combination of several types.
 
 Think about how we'd represent a two-dimensional vector in Haskell.
@@ -881,7 +881,7 @@ ghci> triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]
 We're just drawing from three lists and our output function is combining them into a triple.
 If you evaluate that by typing out `triangles` in GHCI, you'll get a list of all possible triangles with sides under or equal to 10.
 Next, we'll add a condition that they all have to be right triangles.
-We'll also modify this function by taking into consideration that side b isn't larger than the hypothenuse and that side a isn't larger than side b.
+We'll also modify this function by taking into consideration that side b isn't larger than the hypotenuse and that side a isn't larger than side b.
 
 ```{.haskell: .ghci}
 ghci> rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]
diff --git a/markdown/source_md/zippers.md b/markdown/source_md/zippers.md
index 83148a6..b7b6f06 100644
--- a/markdown/source_md/zippers.md
+++ b/markdown/source_md/zippers.md
@@ -544,7 +544,7 @@ First we use `break` to break the list of items in a folder into those that prec
 If you remember, `break` takes a predicate and a list and returns a pair of lists.
 The first list in the pair holds items for which the predicate returns `False`.
 Then, once the predicate returns `True` for an item, it places that item and the rest of the list in the second item of the pair.
-We made an auxilliary function called `nameIs` that takes a name and a file system item and returns `True` if the names match.
+We made an auxiliary function called `nameIs` that takes a name and a file system item and returns `True` if the names match.
 
 So now, `ls` is a list that contains the items that precede the item that we're searching for, `item` is that very item and `rs` is the list of items that come after it in its folder.
 Now that we have this, we just present the item that we got from `break` as the focus and build a breadcrumb that has all the data it needs.