Skip to content

Commit

Permalink
Change <span> tags to <code> and adjust CSS for inline code
Browse files Browse the repository at this point in the history
  • Loading branch information
Gregory Cox committed Mar 16, 2023
1 parent a2563f0 commit 87f70b0
Show file tree
Hide file tree
Showing 17 changed files with 4,627 additions and 4,626 deletions.
1,352 changes: 676 additions & 676 deletions docs/a-fistful-of-monads.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/assets/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ img.center {
margin:10px auto 25px auto;
display:block;
}
pre.code {
pre > code {
color:white;
/*background-color:#522812;*/
background-color:black;
Expand Down Expand Up @@ -105,7 +105,7 @@ pre.code {
background-color:#99DDcc;
color:black;
}
.fixed {
:not(pre) > code:not(.label, .function, .type, .class, .law) {
white-space:nowrap;
font-family:Consolas, "Courier New", monospace;
background-color:#ddd;
Expand Down
1,926 changes: 963 additions & 963 deletions docs/for-a-few-monads-more.html

Large diffs are not rendered by default.

178 changes: 89 additions & 89 deletions docs/functionally-solving-problems.html

Large diffs are not rendered by default.

1,530 changes: 765 additions & 765 deletions docs/functors-applicative-functors-and-monoids.html

Large diffs are not rendered by default.

360 changes: 180 additions & 180 deletions docs/higher-order-functions.html

Large diffs are not rendered by default.

952 changes: 476 additions & 476 deletions docs/input-and-output.html

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/introduction.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ <h2 id="so-whats-haskell">So what’s Haskell?</h2>
<p>
<img src="assets/images/introduction/fx.png" class="right" width="150" height="146" alt="fx">
Haskell is a <strong>purely functional programming language</strong>.
In imperative languages you get things done by giving the computer a sequence of tasks and then it executes them. While executing them, it can change state. For instance, you set variable <span class="fixed">a</span> to 5 and then do some stuff and then set it to something else. You have control flow structures for doing some action several times. In purely functional programming you don’t tell the computer what to do as such but rather you tell it what stuff <em>is</em>. The factorial of a number is the product of all the numbers from 1 to that number, the sum of a list of numbers is the first number plus the sum of all the other numbers, and so on. You express that in the form of functions. You also can’t set a variable to something and then set it to something else later. If you say that <span class="fixed">a</span> is 5, you can’t say it’s something else later because you just said it was 5. What are you, some kind of liar? So in purely functional languages, a function has no side effects. The only thing a function can do is calculate something and return it as a result. At first, this seems kind of limiting but it actually has some very nice consequences: if a function is called twice with the same parameters, it’s guaranteed to return the same result. That’s called referential transparency and not only does it allow the compiler to reason about the program’s behavior, but it also allows you to easily deduce (and even prove) that a function is correct and then build more complex functions by gluing simple functions together.
In imperative languages you get things done by giving the computer a sequence of tasks and then it executes them. While executing them, it can change state. For instance, you set variable <code>a</code> to 5 and then do some stuff and then set it to something else. You have control flow structures for doing some action several times. In purely functional programming you don’t tell the computer what to do as such but rather you tell it what stuff <em>is</em>. The factorial of a number is the product of all the numbers from 1 to that number, the sum of a list of numbers is the first number plus the sum of all the other numbers, and so on. You express that in the form of functions. You also can’t set a variable to something and then set it to something else later. If you say that <code>a</code> is 5, you can’t say it’s something else later because you just said it was 5. What are you, some kind of liar? So in purely functional languages, a function has no side effects. The only thing a function can do is calculate something and return it as a result. At first, this seems kind of limiting but it actually has some very nice consequences: if a function is called twice with the same parameters, it’s guaranteed to return the same result. That’s called referential transparency and not only does it allow the compiler to reason about the program’s behavior, but it also allows you to easily deduce (and even prove) that a function is correct and then build more complex functions by gluing simple functions together.
</p>
<p>
<img src="assets/images/introduction/lazy.png" class="right" width="240" height="209" alt="lazy">
Haskell is <strong>lazy</strong>. That means that unless specifically told otherwise, Haskell won’t execute functions and calculate things until it’s really forced to show you a result. That goes well with referential transparency and it allows you to think of programs as a series of <strong>transformations on data</strong>. It also allows cool things such as infinite data structures. Say you have an immutable list of numbers <span class="fixed">xs = [1,2,3,4,5,6,7,8]</span> and a function <span class="fixed">doubleMe</span> which multiplies every element by 2 and then returns a new list. If we wanted to multiply our list by 8 in an imperative language and did <span class="fixed">doubleMe(doubleMe(doubleMe(xs)))</span>, it would probably pass through the list once and make a copy and then return it. Then it would pass through the list another two times and return the result. In a lazy language, calling <span class="fixed">doubleMe</span> on a list without forcing it to show you the result ends up in the program sort of telling you “Yeah yeah, I’ll do it later!”. But once you want to see the result, the first <span class="fixed">doubleMe</span> tells the second one it wants the result, now! The second one says that to the third one and the third one reluctantly gives back a doubled 1, which is a 2. The second one receives that and gives back 4 to the first one. The first one sees that and tells you the first element is 8. So it only does one pass through the list and only when you really need it. That way when you want something from a lazy language you can just take some initial data and efficiently transform and mend it so it resembles what you want at the end.
Haskell is <strong>lazy</strong>. That means that unless specifically told otherwise, Haskell won’t execute functions and calculate things until it’s really forced to show you a result. That goes well with referential transparency and it allows you to think of programs as a series of <strong>transformations on data</strong>. It also allows cool things such as infinite data structures. Say you have an immutable list of numbers <code>xs = [1,2,3,4,5,6,7,8]</code> and a function <code>doubleMe</code> which multiplies every element by 2 and then returns a new list. If we wanted to multiply our list by 8 in an imperative language and did <code>doubleMe(doubleMe(doubleMe(xs)))</code>, it would probably pass through the list once and make a copy and then return it. Then it would pass through the list another two times and return the result. In a lazy language, calling <code>doubleMe</code> on a list without forcing it to show you the result ends up in the program sort of telling you “Yeah yeah, I’ll do it later!”. But once you want to see the result, the first <code>doubleMe</code> tells the second one it wants the result, now! The second one says that to the third one and the third one reluctantly gives back a doubled 1, which is a 2. The second one receives that and gives back 4 to the first one. The first one sees that and tells you the first element is 8. So it only does one pass through the list and only when you really need it. That way when you want something from a lazy language you can just take some initial data and efficiently transform and mend it so it resembles what you want at the end.
</p>
<p>
<img src="assets/images/introduction/boat.png" class="right" width="160" height="153" alt="boat">
Haskell is <strong>statically typed</strong>. When you compile your program, the compiler knows which piece of code is a number, which is a string and so on. That means that a lot of possible errors are caught at compile time. If you try to add together a number and a string, the compiler will whine at you. Haskell uses a very good type system that has <strong>type inference</strong>. That means that you don’t have to explicitly label every piece of code with a type because the type system can intelligently figure out a lot about it. If you say <span class="fixed">a = 5 + 4</span>, you don’t have to tell Haskell that <span class="fixed">a</span> is a number, it can figure that out by itself. Type inference also allows your code to be more general. If a function you make takes two parameters and adds them together and you don’t explicitly state their type, the function will work on any two parameters that act like numbers.
Haskell is <strong>statically typed</strong>. When you compile your program, the compiler knows which piece of code is a number, which is a string and so on. That means that a lot of possible errors are caught at compile time. If you try to add together a number and a string, the compiler will whine at you. Haskell uses a very good type system that has <strong>type inference</strong>. That means that you don’t have to explicitly label every piece of code with a type because the type system can intelligently figure out a lot about it. If you say <code>a = 5 + 4</code>, you don’t have to tell Haskell that <code>a</code> is a number, it can figure that out by itself. Type inference also allows your code to be more general. If a function you make takes two parameters and adds them together and you don’t explicitly state their type, the function will work on any two parameters that act like numbers.
</p>
<p>
Haskell is <strong>elegant and concise</strong>. Because it uses a lot of high level concepts, Haskell programs are usually shorter than their imperative equivalents. And shorter programs are easier to maintain than longer ones and have less bugs.
Expand All @@ -75,7 +75,7 @@ <h2 id="what-you-need">What you need to dive in</h2>
A text editor and a Haskell compiler. You probably already have your favorite text editor installed so we won’t waste time on that. For the purposes of this tutorial we’ll be using GHC, the most widely used Haskell compiler. The best way to get started is to download <a href="https://www.haskell.org/ghcup/">GHCup</a>, which is the recommended Haskell installer.
</p>
<p>
GHC can take a Haskell file (they usually have a .hs extension) and compile it but it also has an interactive mode which allows you to interactively interact with files. Interactively. You can call functions from files that you load and the results are displayed immediately. For learning it’s a lot easier and faster than compiling every time you make a change and then running the program from the prompt. The interactive mode is invoked by typing in <span class="fixed">ghci</span> at your prompt. If you have defined some functions in a file called, say, <span class="fixed">myfunctions.hs</span>, you load up those functions by typing in <span class="fixed">:l myfunctions</span> and then you can play with them, provided <span class="fixed">myfunctions.hs</span> is in the same folder from which <span class="fixed">ghci</span> was invoked. If you change the .hs file, just run <span class="fixed">:l myfunctions</span> again or do <span class="fixed">:r</span>, which is equivalent because it reloads the current file. The usual workflow for me when playing around in stuff is defining some functions in a .hs file, loading it up and messing around with them and then changing the .hs file, loading it up again and so on. This is also what we’ll be doing here.
GHC can take a Haskell file (they usually have a .hs extension) and compile it but it also has an interactive mode which allows you to interactively interact with files. Interactively. You can call functions from files that you load and the results are displayed immediately. For learning it’s a lot easier and faster than compiling every time you make a change and then running the program from the prompt. The interactive mode is invoked by typing in <code>ghci</code> at your prompt. If you have defined some functions in a file called, say, <code>myfunctions.hs</code>, you load up those functions by typing in <code>:l myfunctions</code> and then you can play with them, provided <code>myfunctions.hs</code> is in the same folder from which <code>ghci</code> was invoked. If you change the .hs file, just run <code>:l myfunctions</code> again or do <code>:r</code>, which is equivalent because it reloads the current file. The usual workflow for me when playing around in stuff is defining some functions in a .hs file, loading it up and messing around with them and then changing the .hs file, loading it up again and so on. This is also what we’ll be doing here.
</p>
<div class="footdiv">
<ul>
Expand Down
Loading

0 comments on commit 87f70b0

Please sign in to comment.