Haskell
Intro
Haskell is a purely functional programming language known for its static typing, lazy evaluation, and mathematical elegance. It was developed in 1990 to create a standardized functional language suitable for both academic and industrial applications.
Unlike imperative languages like Python or Java, Haskell describes what should be done rather than how it should be done. The code is declarative and based on mathematical concepts such as first-class functions, immutability, and monads, which control side effects.
Haskell is often used in fields requiring high reliability and correctness, such as finance, compiler development, and cryptographic applications. Thanks to its strong type safety, it helps catch errors early and write scalable software.
For beginners, Haskell can be challenging because it differs significantly from imperative languages. However, those who embrace it benefit from elegant, expressive code that is often shorter, safer, and easier to test.
Hello world
Lets start with a classic, the hello world. Additionally we are listing odd numbers between 10 and 20.
1main = do
2 putStrLn "Hello world!"
3 putStrLn ("Please look at my favorite odd numbers: " ++ show (filter odd [10..20]))
Expressions
Pure functional
Like already mentioned in the intro, in Haskell nearly everything is an expression.
Expressions do not have any side effects. They describe a value rather than a state.
1x = 5 + 3 -- x is an expression, which returns 8
Lazy evaluation
In Haskell, expressions are evaluated only when they are needed. This enables the use of infinite data structures.
1numbers = [1..] -- Infintive list
2take 5 numbers -- Only now the first 5 values are interepreted [1,2,3,4,5]
Functions are expressions too
Functions in Haskell are "First-Class Citizens" – they can be treated as values, passed to other functions, or returned as results.
1add :: Int -> Int -> Int
2add x y = x+y
3
4-- Eine einfache Funktion, die eine Zahl verdoppelt
5double :: Int -> Int
6double x = x * 2
7
8-- Die Funktion wird als Wert einer Variablen zugewiesen
9myFunction :: Int -> Int
10myFunction = double
11
12-- Anwendung der Funktion
13main :: IO ()
14main = print (myFunction 5) -- Ausgabe: 10
15
16
17-- Eine Funktion, die eine Zahl um 1 erhöht
18increment :: Int -> Int
19increment x = x + 1
20
21-- Die Funktion `increment` wird an `map` übergeben
22-- Funktion als Argument
23main :: IO ()
24main = print (map increment [1, 2, 3]) -- Ausgabe:
25
26
27
28-- Funktion als Rückgabewert
29-- Eine Funktion, die eine neue Funktion zurückgibt
30createMultiplier :: Int -> (Int -> Int)
31createMultiplier n = \x -> x * n
32
33-- Verwendung der zurückgegebenen Funktion
34main :: IO ()
35main = do
36 let double = createMultiplier 2
37 let triple = createMultiplier 3
38 print (double 5) -- Ausgabe: 10
39 print (triple 5) -- Ausgabe: 15
Types
In Haskell, types are a central concept – they ensure that your code remains safe, robust, and easy to understand.
Haskell has a static, strong, and inferential type system, which means:
- Static: The type of every expression is checked at compile time.
- Strong: Type errors result in compilation errors – there is no implicit type conversion.
- Type inference: Haskell can automatically infer many types, so you don’t always have to specify them explicitly.
Haskell provides a variety of built-in data types:
Numbers
Int
– Fixed-size integersInteger
– Arbitrary-precision integers (unlimited size)Float
– Single-precision floating-point numbersDouble
– Double-precision floating-point numbers
1x :: Int
2x = 42
3
4y :: Float
5y = 3.14
Boolean Values
1isEven :: Int -> Bool
2isEven x = x `mod` 2 == 0
Characters and Strings
1greeting :: String
2greeting = "Hello, Haskell!"