Features:
- Purely functional programming language. No side effects. Referential transparency.
- Lazy.
- Statically typed. Type inference.
- Elegant and concise.
- Made by some really smart guys.
Basic arithmetic:
The operators are functions. For instance, * is a function that takes two numbers and multiplies them. This is what we call an infix function. Most functions that aren’t used with numbers are prefix functions. Functions are usually prefix so from now on, we’ll just assume it.
In Haskell, functions are called by writing the function name, a space and then the parameters, separated by spaces. Calling a function with several parameters is also simple. Function application has the highest precedence of them all.
succ 8
> 9
min 1 1.1
> 1If a function takes two parameters, we can also call it as an infix function by surrounding it with backticks.
div 92 10
92 `div` 10Functions are defined in a similar way they are called. The function name is followed by parameters separated by spaces. Functions in Haskell don’t have to be in any particular order.
:l baby
Naming rules:
- The apostrophe does not have any special meaning in Haskell’s syntax. It’s a valid character to use in a function name. We usually use to denote a strict version of a function (one that isn’t lazy) or a slightly modified version of a function or a variable.
- The functions can’t begin with uppercase letters.
- When a function doesn’t take any parameters it’s a definition (or a name).
- We can use
letkeyword to define a name in GHCI which is equivalent to writing=in script and then loading it.
If-else:
doubleNumber x = if x > 100
then x
else x*2The difference between Haskell’s if statement and if statements in imperative languages is that the else part is mandatory in Haskell. In imperative languages you can just skip a couple of steps if the condition isn’t satisfied but in Haskell every expression and function must return something. Another thing about the if statement in Haskell is that it is an expression.
Lists:
Lists are a homogeneous data structure. It stores several elements of the same type. 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. Speaking of characters, strings are just lists of characters.
"hello"is a syntactic sugar for['h', 'e', 'l', 'l', 'o']- A common task of putting two lists together is done by using the
++operator. - When you put together two lists (even if append a singleton list), Haskell has to walk through the whole list on left side.
- Putting something at the beginning of a list using
:operator is instantaneous. [1,2,3]is actually a syntactic sugar for1:2:3:[]where[]is an empty list.- If you want to index a list use
!!as in"Steve Buscemik" !! 6. - Lists can also contain lists. The lists within a list can be of different length but they can’t be of different types.
- Lists can be compared if the stuffs they contain can be compared. They are compared in lexicographical order.
Here are some basic functions that operate on lists.
- init, length, reverse, maximum, product, sum
- take, drop, elem
- ranges:
[1..20],['a'..'z'],[2,4..20],[20,19..1] - infinite lists: cycle, repeat
List comprehension:
-
[x*2 | x <- [1..10]] -
Predicates go after the binding parts and are separated from them by a comma. `[x2 | x ← [1..10], x2 >= 12]
-
We can include several predicates. Not only can we have multiple predicates in list comprehensions (an element must satisfy all the predicates to be included in the resulting list), we can also draw from several lists. When drawing from several lists, comprehensions produce all combinations of the given lists and then join them by the output function we supply. A list produced by a comprehension that draws from two lists of length 4 will have a length of 16, provided we don’t filter them.
[x*y | x <- [2,5,10], y <- [8,10,11], x*y >= 50] -
Because strings are lists, we can use list comprehension to process and produce strings.
Tuples:
Tuples are like lists. They are a way to store several values into a single value. However, there are 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.
Another key difference is that they don’t have to be homogeneous. Unlike a list, a tuple can contain a combination of several types.
[[1,2], [8,11], [4,5]]- not
[(1,2), (8,11,12), (4,5)] - not
[(1,2), ("one", 2)] - No singleton tuples
- Functions:
fst,snd
A cool function that produces a list of pairs: zip. It takes two lists and then zips them together into one list by joining the matching elements into pairs.