category feedOld-style Haskell manualGuides and tutorialseditdelete

This category is a work in progress






I always thought that for someone smart and curious, the right way to learn programming is how it was done in the Olden Days – with BASIC and a manual that didn't spend ten pages explaining each concept.

I looked around and haven't found anything like this, so here's a tutorial for Haskell that follows that style. (See the BBC Micro manual for inspiration.) It describes one thing, and one only: how to get the computer do what you want. Which is pretty useful, isn't it?

edit description
or press Ctrl+Enter to savemarkdown supported
#
Writing and running programs
other
move item up move item down edit item info delete item
Summary edit summary

The command stack runghc foo.hs runs a program contained in foo.hs. For instance, this program prints “Hello world” to the screen:

-- This should be put into a file called 'foo.hs'.
--
-- Lines starting with “--” are comments and they
-- are ignored by Haskell.

main = do
  putStrLn "Hello world"

stack can be obtained here: https://docs.haskellstack.org/en/stable/README/#how-to-install. Before running programs, you would need to install a compiler; to do that, run stack setup.


Note 1: lines starting with -- are comments. They can be left in code or deleted, as you wish. You may want to leave comments in your programs even if you understand everything at the moment of writing, because later on you might forget and become unable to read your own code.

Summary quit editing summary
#
Calculations
other
move item up move item down edit item info delete item
Summary edit summary

Here's a program that calculates sum of all numbers between one number and another:

main = do
  a <- readLn                                                 -- (1)
  b <- readLn
  putStrLn ("There are " ++ show (b-a+1) ++ " numbers")       -- (2)
  putStrLn ("Their sum is " ++ show (sum [a..b]))             -- (3)

a <- readLn takes the entered input and turns it into something before putting it into a – in our case, a number. The readLn action is equivalent to this:

readLn = read <$> getLine

read is a function that can convert a string to a number (or something else, as needed).

In lines (2) and (3) we use the opposite of read – i.e. show – to turn the result of a calculation into a string. This is needed because ++ can't add a string to a number, or a number to a string – it needs two strings.

Finally, sum [a..b] lists all numbers between a and b and calculates their sum. If you wrote show [a..b] instead of show (sum [a..b]), the numbers themselves would've been printed. Try it.


Note 1: you may be curious what <$> is. It's an operator that says “do something with the result”. For instance, we could write length <$> getLine instead of read <$> getLine to make an action that gets entered text and gives you a number saying how many characters are in that text.

Note 2: there are several operators for doing something with the result, and they have to be used in different cases. If you want to do something with the result of a simple computation (like 2+3), don't use any operator. If you have an action (like getLine), you should use <$>. However, if you have an action and you want to perform another action on its result (like printing it), use =<<.

            |       action         |     value      |
------------+----------------------+----------------+
action      | putStrLn =<< getLine |   print [1..3] |
computation |   read <$> getLine   |  length [1..3] |

Later we'll give precise rules about how to find out what operator should be used in what case.

Summary quit editing summary
#
Reading and writing text
other
move item up move item down edit item info delete item
Summary edit summary

Here's a program that waits for a name to be entered and then prints it:

main = do
  name <- getLine                   -- (1)
  putStrLn ("Hello, " ++ name)      -- (2)

name <- getLine takes entered text and calls it name so that in the rest of the program we'd be able to use it. In the line (2) we add “Hello” to name and show the result on screen.


Note 1: of course, the original name doesn't change when we do putStrLn ("Hello, " ++ name). If it did, that'd be pretty inconvenient.

Note 2: parentheses around ("Hello, " ++ name) are important. Without them, putStrLn would try to print "Hello, " instead of "Hello, " ++ name, and then ++ name would confuse the compiler and you'll see this error:

foo.hs:3:3: error:
    • Couldn't match expected type ‘[Char]’ with actual type ‘IO ()’
    • In the first argument of ‘(++)’, namely ‘putStrLn "Hello, "’
      In a stmt of a 'do' block: putStrLn "Hello, " ++ name
      In the expression:
        do { name <- getLine;
             putStrLn "Hello, " ++ name }
Summary quit editing summary
#
Functions
other
move item up move item down edit item info delete item
Summary edit summary

write something here!

Summary quit editing summary
#
Loops
other
move item up move item down edit item info delete item
Summary edit summary

write something here!

Summary quit editing summary
#
A small game: Mastermind
other
move item up move item down edit item info delete item
Summary edit summary

write something here!

Summary quit editing summary
#
A small game: Guess-the-number
other
move item up move item down edit item info delete item
Summary edit summary

write something here!

Summary quit editing summary
#
Lists
other
move item up move item down edit item info delete item
Summary edit summary

write something here!

Summary quit editing summary