Please Buy now at Leanpub
Written and illustrated by GetContented.
Published on 2017-06-27.
Covers: writing programs to create basic output
Let’s start writing some software! At this point, you should find out how to use an interactive Haskell environment because we’ll be using it to check types and run code. An internet search will help you to find this. There are countless tutorials on how to set up and install this software, and it has a tendency to change, so we won’t repeat them here, but if you’re using GHC, then you will already have the interactive environment GHCi installed, which is what we’ll be using. A good start is to go to http://www.haskell.org/ and to use the stack environment because it sorts out a lot of the common problems with setup and installation.
In particular, when you write your Haskell files in a text editor, you load them into GHCi with the
:load filename (or
:l filename) command and then you can run
main and other functions by typing
main and pressing the return key. You can also check types by using the
:t) command in front of an expression, and when you’ve changed your code, you can use
:r) to reload the file, which gives a pretty nice workflow for constantly type-checking your work.
You’ll also need a text editor. Atom, Sublime Text or Textmate are reasonably good ones, depending on if you’re on Windows or Mac.
In a later update to this tutorial, we will most likely address setting up Haskell and which tools to use.
We begin by taking a number of simple, graded exercises. By now, you’re familiar with recognising the
String values and their types. Doing these exercises, and then revising them later will anchor these things in your long term memory.
To do them, we’ll run through some ways to think about solving them together, then at the end you will get to solve similar problems on your own. You should not look at the example run-throughs when you’re doing your own programs, otherwise you won’t build your own real-world usage understanding. If you have to look, that’s fine, however once you’ve finished, you should do that exercise again from the start without looking.
These exercises may seem stupidly simple at first, but they’re designed to get you to think in a way that will pay off as the programs get more complicated and larger with time.
Task: Write a program to print “Hello” on the screen.
We can immediately see we’ll need the
"Hello", so let’s create a definition for that, and its type:
helloString :: String helloString = "Hello"
If we didn’t already know the type of
"Hello", we could ask GHCi by typing
:t "Hello" at the prompt, and it will tell us
"Hello" :: [Char] and as we know,
String is a type synonym for
[Char]. This can be very helpful for working out the types of expressions and values so we know what will work with what.
So now we have our
String, we want to be able to print it on the screen. This will be an
IO action, and as we know, Haskell programs always start with the
main, so we will need to make a definition for that. The type of
main has to be
So, on the one hand we have
helloString whose type is
String, and on the other, we need a definition for
main whose type is
So we want a function whose type is
String -> IO (). We could use the hoogle Haskell search (at https://www.haskell.org/hoogle/) to find this for us by typing in the type signature to its search feature, but we happen to already know of a function whose type matches this, because we’ve seen it many times by now:
putStrLn has type
String -> IO (), and we know that means if we apply a
String value to it by putting it to the right of it, together they will be an expression whose type is
IO (). We also know how to make definitions: you write a name on the left, an equals sign, then an expression on the right.
So, we can join all of this information up, and finish our program:
helloString :: String helloString = "Hello" main :: IO () main = putStrLn helloString
Task: Write a program to add the number 3029 to 2938 then print the answer on the screen by itself.
Ok, we’ll use a top-down approach this time. We know we’ll need to have a program that prints a number on the screen.
We’re very familiar with printing numbers on the screen by now. We can either use
putStrLn with a
String version of the number, or the
Integer is), so let’s write our program “as if” we already had the addition expression that evaluated to a single number. To do this, we can “dummy in” a definition of a single number (let’s use
0 for now):
theAnswerNumber :: Integer theAnswerNumber = 0 main :: IO () main = print theAnswerNumber
If you compile this and load it into GHCi, it will work just fine.
Now, the only thing that remains is to work out how to change that expression from just
0 to an expression that will add the numbers together, and we know about the
(+) operator which takes two numbers, and returns their sum. Let’s use it:
theAnswerNumber :: Integer theAnswerNumber = 3029 + 2938 main :: IO () main = print theAnswerNumber
Task: Write a program to print the product (multiplied value) of
Again, we know the type of
IO (), and we know the type of
Show a => a -> IO (), so we’ll feed
main :: IO () main = print 0
Now we have this, what if we just replace the value
33 * 398? Well, in Haskell we know that a space between things will mean we want function application, and we know that this is very high precedence, and it’ll apply from left to right, so
print 33 * 398 would mean the same thing as
(print 33) * 398, and if we try that, Haskell will give us this type error, because it’d be trying to apply
(*) to an
IO () value...:
No instance for (Num (IO ())) arising from a use of ‘*’.
That means it first bound
IO (), and then tried to pass that
IO () value into
(*) as one of its arguments, which didn’t work, because the type of
Num a => a -> a -> a, not
IO (), which does not have an instance of the
Num typeclass. That’s what that error message says.
So, we need to use brackets to turn
33 * 398 into a single expression which can be passed as the one argument to
main :: IO () main = print (33 * 398)
Now it’s your turn!
Task: Write a program that prints
"This sentence is false" on the screen. Once you’ve done this, make it say
"No it's not" instead. Once you’ve done this, change it to say
"One plus two is not seven".
Task: Write a program that prints the number
20938 on the screen.
Task: Write a program that adds the number of whatever the current month is right now (
1 is for January,
2 is for February etc.) to the current year, and prints it on the screen. (Note: it needn’t actually generate or get the current month, you just write it in as a number yourself).
Task: Write a program that multiplies your current age with your mother’s current age and prints it on the screen. (Just write the values you know for these ages in as numbers, you don’t need to make the computer actually get the numbers from the user).
Task: Write a program that adds the numbers
9 together and prints the result on the screen.
Task: Write a program that subtracts
1098 and prints it on the screen.
If you’ve enjoyed reading this, please consider purchasing a copy at Leanpub today
Please follow us, and check out our videos Follow @HappyLearnTutes
Also, Volume 2 is now in beta and being written! Show your support and register your interest at its Leanpub site.