Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/functors-applicative-functors-and-monoids.html
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ <h1>Functors, Applicative Functors and Monoids</h1>
fmap f (Just x) = Just (f x)
fmap f Nothing = Nothing
</pre>
<p>We imagine that <span class="fixed">id</span> plays the role of the <span class="fixed">f</span> parameter in the implementation. We see that if wee <span class="fixed">fmap id</span> over <span class="fixed">Just x</span>, the result will be <span class="fixed">Just (id x)</span>, and because <span class="fixed">id</span> just returns its parameter, we can deduce that <span class="fixed">Just (id x)</span> equals <span class="fixed">Just x</span>. So now we know that if we map <span class="fixed">id</span> over a <span class="fixed">Maybe</span> value with a <span class="fixed">Just</span> value constructor, we get that same value back.</p>
<p>We imagine that <span class="fixed">id</span> plays the role of the <span class="fixed">f</span> parameter in the implementation. We see that if we <span class="fixed">fmap id</span> over <span class="fixed">Just x</span>, the result will be <span class="fixed">Just (id x)</span>, and because <span class="fixed">id</span> just returns its parameter, we can deduce that <span class="fixed">Just (id x)</span> equals <span class="fixed">Just x</span>. So now we know that if we map <span class="fixed">id</span> over a <span class="fixed">Maybe</span> value with a <span class="fixed">Just</span> value constructor, we get that same value back.</p>
<p>Seeing that mapping <span class="fixed">id</span> over a <span class="fixed">Nothing</span> value returns the same value is trivial. So from these two equations in the implementation for <span class="fixed">fmap</span>, we see that the law <span class="fixed">fmap id = id</span> holds.</p>
<img src="assets/images/functors-applicative-functors-and-monoids/justice.png" alt="justice is blind, but so is my dog" class="left" width="345" height="428">
<p><em>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.</em> Formally written, that means that <span class="label law">fmap (f . g) = fmap f . fmap g</span>. Or to write it in another way, for any functor <i>F</i>, the following should hold: <span class="label law">fmap (f . g) F = fmap f (fmap g F)</span>.</p>
Expand Down Expand Up @@ -512,7 +512,7 @@ <h1>Functors, Applicative Functors and Monoids</h1>
True
</pre>
<p><span class="fixed">sequenceA [(&gt;4),(&lt;10),odd]</span> creates a function that will take a number and feed it to all of the predicates in <span class="fixed">[(&gt;4),(&lt;10),odd]</span> and return a list of booleans. It turns a list with the type <span class="fixed">(Num a) =&gt; [a -&gt; Bool]</span> into a function with the type <span class="fixed">(Num a) =&gt; a -&gt; [Bool]</span>. Pretty neat, huh?</p>
<p>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 <span class="fixed">[ord, (+3)]</span>, because <span class="fixed">ord</span> takes a character and returns a number, whereas <span class="fixed">(+3)</span> takes a number and returns a number.</p>
<p>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 <span class="fixed">[ord, (+3)]</span>, because <span class="fixed">ord</span> takes a character and returns a number, whereas <span class="fixed">(+3)</span> takes a number and returns a number.</p>
<p>When used with <span class="fixed">[]</span>, <span class="fixed">sequenceA</span> 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 <span class="fixed">sequenceA</span> and then done with a list comprehension:</p>
<pre name="code" class="haskell:hs">
ghci&gt; sequenceA [[1,2,3],[4,5,6]]
Expand Down
2 changes: 1 addition & 1 deletion docs/higher-order-functions.html
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ <h1 style="margin-left:-3px">Higher order functions</h1>
sum' = foldl (+) 0
</pre>
<p>The lambda function <span class="fixed">(\acc x -&gt; acc + x)</span> is the same as <span class="fixed">(+)</span>. We can omit the <span class="fixed">xs</span> as the parameter because calling <span class="fixed">foldl (+) 0</span> will return a function that takes a list. Generally, if you have a function like <span class="fixed">foo a = bar b a</span>, you can rewrite it as <span class="fixed">foo = bar b</span>, because of currying.</p>
<p>Anyhoo, let's implement another function with a left fold before moving on to right folds. I'm sure you all know that <span class="fixed">elem</span> 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. </p>
<p>Anyhow, let's implement another function with a left fold before moving on to right folds. I'm sure you all know that <span class="fixed">elem</span> 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. </p>
<pre name="code" class="haskell:hs">
elem' :: (Eq a) =&gt; a -&gt; [a] -&gt; Bool
elem' y ys = foldl (\acc x -&gt; if x == y then True else acc) False ys
Expand Down
2 changes: 1 addition & 1 deletion docs/input-and-output.html
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ <h1>Input and Output</h1>
</pre>
<img src="assets/images/input-and-output/police.png" width="241" height="328" alt="Stop right there, criminal scum! Nobody breaks the law on my watch! Now pay your fine or it's off to jail." class="left">
<p>Pure code can throw exceptions, but they can only be caught in the I/O part of our code (when we're inside a <i>do</i> block that goes into <span class="fixed">main</span>). 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.</p>
<p>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 <span class="fixed">Either</span> and <span class="fixed">Maybe</span> to represent results that may have failed.</p>
<p>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 <span class="fixed">Either</span> and <span class="fixed">Maybe</span> to represent results that may have failed.</p>
<p>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 <span class="fixed">main</span>. 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.</p>
<pre name="code" class="haskell:hs">
import System.Environment
Expand Down
4 changes: 2 additions & 2 deletions docs/starting-out.html
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ <h1 style="margin-left:-3px">Starting Out</h1>
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.
</p>
<p>
In Haskell, lists are a <em>homogenous</em> 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 <em>homogeneous</em> 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!
</p>
<pre name="code" class="haskell: ghci">
ghci&gt; lostNumbers = [4,8,15,16,23,42]
Expand Down Expand Up @@ -479,7 +479,7 @@ <h1 style="margin-left:-3px">Starting Out</h1>
<a name="tuples"></a><h2>Tuples</h2>
<img src="assets/images/starting-out/tuple.png" alt="tuples" class="right" width="160" height="162">
<p>In some ways, tuples are like lists &mdash; 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.</p>
<p>Another key difference is that they don't have to be homogenous. Unlike a list, a tuple can contain a combination of several types.</p>
<p>Another key difference is that they don't have to be homogeneous. Unlike a list, a tuple can contain a combination of several types.</p>
<p>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 <span class="fixed">[[1,2],[8,11],[4,5]]</span>. The problem with that method is that we could also do stuff like <span class="fixed">[[1,2],[8,11,5],[4,5]]</span>, 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: <span class="fixed">[(1,2),(8,11),(4,5)]</span>. What if we tried to make a shape like <span class="fixed">[(1,2),(8,11,5),(4,5)]</span>? Well, we'd get this error:</p>
<pre name="code" class="haskell: ghci">
• Couldn't match expected type ‘(a, b)’
Expand Down
2 changes: 1 addition & 1 deletion markdown/source_md/functionally-solving-problems.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion markdown/source_md/higher-order-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion markdown/source_md/input-and-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion markdown/source_md/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions markdown/source_md/starting-out.md
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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]
Expand Down
Loading