Haskell

Table of Contents

Stems from lambda calculus, with the lower details, such as integers, boolean, …, left to the compiler.

All functions are Pure Function, function as in mathmetical functions, and declarative. it does not care about the order of lines.

1. Syntax

1.1. Definition

Function

square :: Num a => a -> a  -- define types
square x = x * x           -- define operations

\x y -> x + y              -- anonymous function. '\' because it looks like 'λ'

as-pattern (or alias pattern) can be used when defining a function on a data structure

printAge u@(User name age) = do
  putStrLn ("The user's age is " ++ show age)
  saveUserToDatabase u -- 'u' is bound to (User name age)

where and let-in keywords

magnitude x y = z where
  z = sqrt (x*x + y*y)

Tuple

p1 :: (Float, Float, Float)
p1 = (1.0, 2.0, 1.0)

Data Type (Struct)

data Point3D = Point Float Float Float
data List a = L a (List a) | Empty      -- With generic type a

A data type Point3D can be constructed by the constructor function Point.

There is an alternative way to define a data type called record syntax

data Person = Person
  { firstName :: String
  , lastName  :: String
  , age       :: Int
  }

alex = Person { firstName = "Alex", lastName = "Smith", age = 28 }
main = putStrLn (firstName alex)  -- the member access functions are auto-generated

olderAlex = alex { age = 29 }     -- update is done incrementally

1.2. Branching

if-else statement

x = if condition then this else that

Pattern matching

fib :: Num a => a -> a
fib 0 = 1
fib 1 = 1
fib n = fib (n-2) + fib (n-1)

case-of statement

case a of
  1 -> this
  2 -> that
  _ -> exit

Guarding

sign x
  | x >= 0 = 1
  | x <  0 = -1
  | otherwise = 0

1.3. List

In haskell, there only exist linked lists.

Definition

list = [1, 2, 3]
list = 1:(2:(3:[]))

where : (cons) represents the operation of joining two

Indexing

x = [1, 2, 3] !! 0 -- 1

A range can be expressed easily with

[1..10000]

1.4. Recursion

Because of its functional nature, haskell only supports recursion rather than iteration. It's not a problem because every iteration can be expressed in recursion, and in terms of handling call stack, Haskell does its best to optimize it.

Recursion can be done by destructuring a list

sum :: [Int] -> Int
sum (x:xs) = x + sum xs

1.5. Evaluation

Function can be prefixed or infixed

elem 3 [1, 2, 3]
3 `elem` [1, 2, 3] -- prefix to infix

3 + 5
(+) 3 5            -- infix to prefix

Composition

(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)

This is useful when composing function before the arguments are given.

Apply

($) :: (a -> b) -> a -> b
f $ x = f x

Currying

f :: Int -> Int -> Int
f a b = a + b

g :: Int -> Int
g = f 1    -- curried

2. Functions

Arithmetics

=const
forall a b. a -> b -> a=

List

=head
[a] -> a=
=tail
[a] -> [a]=
=length
[a] -> Int=
=reverse
[a] -> [a]=
  • Notice reverse xs = foldl (\acc x -> x : acc) [] xs
=take
forall a. Int -> [a] -> [a]=
=takeWhile
forall a. (a -> Bool) -> [a] -> [a]=
=drop
forall a. Int -> [a] -> [a]=
=dropWhile
forall a. (a -> Bool) -> [a] -> [a]=
=scanl
(b -> a -> b) -> b -> [a] -> [b]=
=foldl
(b -> a -> b) -> b -> [a] -> b= nest operations to the left, calculate from the left
  • Example: foldl f z [1, 2, 3] = f (foldl f z [1, 2]) 3
  • Use =foldl' :: (b -> a -> b) -> b -> [a] -> b= for eager evaluation
=map
(a -> b) -> [a] -> [b]=
  • Notice map f xs = foldr (\x acc -> f x : acc) [] xs
=filter
(a -> Bool) -> [a] -> [a]=
  • Notice filter p xs = foldr (\x acc -> if p x then x : acc else acc) [] xs

Function

=map
Functor f > (a -> b) -> f a -> f b

IO

=show
forall a. Show a > a -> String

3. Monad

See monad

Bind

(>>=) :: Monad m => m a -> (a -> m b) -> m b

It corresponds to flatMap in other languages

>> :: Monad m => m a -> m b -> m b can be used when the first value is being discarded.

Join

join :: Monad m => m (m a) -> m a

3.1. Maybe Monad

Maybe type constructor

Maybe a = Just a | Nothing

r :: a -> Maybe a -- return
r x = Just x

f :: a -> Maybe b
g :: b -> Maybe c

-- f g
-- [\a -> Maybe b]   [\b -> Maybe c]
-- \a -> [Maybe b >>= \b -> Maybe c]
-- >>= :: Maybe b  -> (b -> Maybe c) -> Maybe c

Maybe a >>= g = case Maybe a of
          Nothing -> Nothing
          Just b -> g b

3.2. IO Manad

takes "world" as input and produces another "world" as an output

main :: IO ()
main = do
  input <- getLine  -- () -> IO(String)
  writeFile "result.txt" (map toUpper input) -- Path -> String -> IO()

4. Packages

Module can be defined with

module Module
  ( f1, f2, f3 ) where
f1 :: ...
f2 :: ...
f3 :: ...

and imported in other file with

import Module
import Module (f1, f2)
import qualified Module as Mod

a = f1
c = Mod.f3

A type can be imported with all-inclusive wildcard so that all of its constructors and fields are imported alongside

import Data.Maybe (Maybe(..))
  -- Just, Nothing are also imported

The packages are stored in /usr/lib/ghc-N.N.N/site-local/ in the form of *.dyn_hi

4.1. System.IO

=getLine
IO String=
=putStr
String -> IO ()= write to standard out

4.2. Data.Bits

  • (.|.) Bitwise OR

5. Compiler

  • ghc: The Glasgow Haskell Compiler
    • -dynamic use dynamic linking. Use this if Haskell is installed as shared library, for example on Arch.
  • ghc-static compile using static linking
  • ghc-libs dynamic libraries

Author: Jeemin Kim

Created: 2026-07-18 Sat 19:35