Part 15

Expressions and Types

Just like we saw in the GHCi example above, expressions and types are the bread and butter of Haskell. In fact, almost everything in a Haskell program is an expression. In particular, there are no statements like in Python, Java or C.

An expression has a value and a type. We write an expression and its type like this: expression :: type. Here are some examples:

ExpressionTypeValue
TrueBoolTrue
not TrueBoolFalse
'a'Char'a'
"as" ++ "df"[Char]"asdf"

Syntax of Expressions

Expressions consist of functions applied to arguments. Functions are applied (i.e. called) by placing the arguments after the name of the function – there is no special syntax for a function call.

HaskellPython, Java or C
f 1f(1)
f 1 2f(1,2)

Parentheses can be used to group expressions (just like in math and other languages).

HaskellPython, Java or C
g h f 1g(h,f,1)
g h (f 1)g(h,f(1))
g (h f 1)g(h(f,1))

Some function names are made special characters and they are used as operators: between their arguments instead of before them. Function calls bind tighter than operators, just like multiplication binds tighter than addition.

HaskellPython, Java or C
a + ba + b
f a + g bf(a) + g(b)
f (a + g b)f(a+g(b))

PS. in Haskell, function application associates left, that is, f g x y is actually the same as (((f g) x) y). We’ll get back to this topic later. For now you can just think that f g x y is f applied to the arguments g, x and y.

Syntax of Types

Here are some basic types of Haskell to get you started.

TypeLiteralsUseOperations
Int1, 2, -3Number type (signed, 64bit)+, -, *, div, mod
Integer1, -2, 900000000000000000Unbounded number type+, -, *, div, mod
Double0.1, 1.2e5Floating point numbers+, -, *, /, sqrt
BoolTrue, FalseTruth values&&, ||, not
String aka [Char]"abcd", ""Strings of charactersreverse, ++

As you can see, the names of types in Haskell start with a capital letter. Some values like True also start with a capital letter, but variables and functions start with a lower case letter (reverse, not, x). We’ll get back to the meaning of capital letters in the next part.

Function types are written using the -> syntax:

  • A function of one argument: argumentType -> returnType
  • … of two arguments: argument1Type -> argument2Type -> returnType
  • … of three arguments: argument1Type -> argument2Type -> argument3Type -> returnType

Looks a bit weird, right? We’ll get back to this as well.

Note About Misleading Types

Sometimes, the types you see in GHCi are a bit different than what you’d assume. Here are two common cases.

Prelude> :t 1+1
1+1 :: Num a => a

For now, you should read the type Num a => a as “any number type”. In Haskell, number literals are overloaded which means that they can be interpreted as any number type (e.g. Int or Double). We’ll get back to what Num a actually means when we talk about type classes later, in chapter 18.

Prelude> :t "asdf"
"asdf" :: [Char]

The type String is just an alias for the type [Char] which means “list of characters”. We’ll get back to lists on the next chapter! In any case, you can use String and [Char] interchangeably, but GHCi will mostly use [Char] when describing types to you.

You have reached the end of this section! Continue to the next section:

You can check your current points from the blue blob in the bottom-right corner of the page.