Siksha Sarovar

Siksha Sarovar (sikshasarovar.com) is a free educational web application that helps students in India learn programming and prepare for academic and competitive exams. The platform offers structured coding courses (C, C++, Python, Java, HTML, CSS, PHP, Power BI, AI, Machine Learning, Data Science), complete university curriculum notes for BCA/MCA students with previous year question papers, Class 10 and Class 12 CBSE/HBSE school notes, and dedicated preparation material for SSC, UPSC, Banking, Railway and other government exams. Browsing the site is completely free and requires no account. Users may optionally sign in with Google solely to save their learning progress, quiz scores and personal preferences across devices.

Privacy Policy | Terms of Service | Contact Siksha Sarovar | About Siksha Sarovar

v4.0.9 · PWA
Siksha Sarovar logo
Siksha Sarovar
Your Learning Universe

Siksha Sarovar is a free e-learning platform for coding courses, BCA university notes and competitive exam preparation. Optional Google sign-in saves your learning progress across devices.

Initializing knowledge base…
Compiling modules 0%

Unit 1: Basic Types, Definitions & Designing Programs

Lesson 3 of 17 in the free Functional & Logic Programming notes on Siksha Sarovar, written by Rohit Jangra.

2.1 The basic types of Haskell

TypeValuesExample literals
Booltruth valuesTrue, False
Intfixed-size integers (at least 30 bits)42, -7
Integerarbitrary-precision integers2^100 works exactly
Float / Doublefloating point numbers3.14, 2.0e3
Charsingle characters'a', '9', '\n'
String= [Char], a list of characters"hello"

Every expression has a type, written with :: ("has type"):

True && False       :: Bool
'x'                 :: Char
"functional"        :: String
(3 < 5)             :: Bool

2.2 Operators you must know

  • Arithmetic: + - * / and for integers div, mod (div 7 2 = 3, mod 7 2 = 1 — usually written infix with backquotes around the name), exponent ^.
  • Comparison: == /= < <= > >= — note /= is "not equal" (≠).
  • Boolean: && (and), || (or), not.

2.3 Function definitions — the three styles

1. Simple equation:

double :: Int -> Int
double n = 2 * n

2. Conditional expression (if–then–else). In Haskell if is an expression — it produces a value, so the else branch is compulsory:

maxOf2 :: Int -> Int -> Int
maxOf2 a b = if a >= b then a else b

3. Guards — the most readable style for multi-way decisions:

grade :: Int -> String
grade marks
  | marks >= 90 = "A+"
  | marks >= 75 = "A"
  | marks >= 60 = "B"
  | marks >= 40 = "C"
  | otherwise   = "Fail"

Guards are tried top to bottom; otherwise is just a constant equal to True, used as a catch-all.

2.4 Local definitions: where and let

-- where: definitions used by the whole right-hand side
heronArea :: Double -> Double -> Double -> Double
heronArea a b c = sqrt (s * (s-a) * (s-b) * (s-c))
  where s = (a + b + c) / 2

-- let ... in: a local definition inside an expression
cylinderVol :: Double -> Double -> Double
cylinderVol r h = let base = pi * r * r in base * h

2.5 Multi-argument functions and currying

The type maxOf2 :: Int -> Int -> Int reads as Int -> (Int -> Int): maxOf2 takes one Int and returns a function that takes the second Int. This is called currying (after Haskell B. Curry — yes, the language is named after him too).

Practical payoff — partial application:

add :: Int -> Int -> Int
add x y = x + y

increment :: Int -> Int
increment = add 1        -- supply only the first argument!

ghci> increment 41
42

2.6 Designing and writing programs — the recipe

Haskell programs are designed type-first. For every function:

  1. Name it and write its type signature — what goes in, what comes out.
  2. Enumerate the cases of the input (zero/non-zero, empty/non-empty list, ...).
  3. Write one equation per case. Trust recursion for the "smaller" case.
  4. Test in GHCi with normal cases and edge cases.

Worked example — design power x n computing xⁿ for n ≥ 0:

-- Step 1: the type
power :: Double -> Int -> Double

-- Step 2: cases on n —  n == 0  is the base case, n > 0 recursive
-- Step 3: one equation per case
power x 0 = 1.0
power x n = x * power x (n - 1)

-- Step 4: test
-- power 2 10 → 1024.0 ;  power 5 0 → 1.0

Hand-evaluation (always practise this — it is a standard exam question):

power 2 3
= 2 * power 2 2
= 2 * (2 * power 2 1)
= 2 * (2 * (2 * power 2 0))
= 2 * (2 * (2 * 1.0))
= 8.0

2.7 Currying, precisely — how to read multi-arrow types

-> is right-associative and application is left-associative, so the two bracketings below say the same thing:

add :: Int -> Int -> Int      means   add :: Int -> (Int -> Int)
add 2 3                       means   (add 2) 3
Definition (currying). Representing a function of n arguments as a chain of n single-argument functions, each returning the next. The converse view — bundling the arguments into one tuple — is the uncurried form (Int, Int) -> Int. The standard converters are curry and uncurry.
ghci> :t curry
curry :: ((a, b) -> c) -> a -> b -> c
ghci> uncurry add (2, 3)
5

Why exams love this: "Explain currying and partial application with an example" is a standard 5-mark question. Structure the answer as: definition → type bracketing → one partial-application example (like increment = add 1) → one practical payoff (map (add 10) xs needs no lambda).

2.8 More worked designs (each a past-style exam program)

Leap year with guards:

isLeap :: Int -> Bool
isLeap y
  | y `mod` 400 == 0 = True
  | y `mod` 100 == 0 = False
  | y `mod` 4   == 0 = True
  | otherwise        = False

-- isLeap 2000 → True ; isLeap 1900 → False ; isLeap 2024 → True

Roots of a quadratic — where sharing a subcomputation, tuple result:

roots :: Double -> Double -> Double -> (Double, Double)
roots a b c = ((-b + d) / (2*a), (-b - d) / (2*a))
  where d = sqrt (b*b - 4*a*c)

-- roots 1 (-5) 6 → (3.0, 2.0)

Greatest common divisor — recursion on numbers (Euclid):

hcf :: Int -> Int -> Int
hcf a 0 = a
hcf a b = hcf b (a `mod` b)
hcf 12 18 = hcf 18 12 = hcf 12 6 = hcf 6 0 = 6

2.9 let vs where — when to use which

Featurewherelet ... in
Positionafter the whole right-hand sideinside any expression
Scopeall guards/equations of that clauseonly the in expression
Is it an expression?no (syntax attached to a definition)yes — usable anywhere an expression fits
Typical useshared helper across several guardssmall local value mid-computation

Both may define several names and even local functions; indentation determines where the block ends (the layout rule: definitions in a block must start in the same column).

2.10 Common beginner errors the examiner probes

MistakeWhy it failsFix
square -2parsed as square - 2 (subtraction!)square (-2)
if x > 0 then 1if is an expression — else compulsoryadd else 0
f x+1 hoping for f (x+1)application binds tighter than +f (x+1)
3 + 4.5 with 3 :: IntInt and Double never mix silentlyfromIntegral n + 4.5
Guard with no otherwise falling throughnon-exhaustive guards crash at runtimeend with otherwise

Exam pointers

  • Memorise the basic-types table (§2.1) — "list the basic types of Haskell with examples" is a direct 3-mark question.
  • For any "write a function" question: signature first, cases second, equations third, then a two-line test — this mirrors the design recipe of §2.6 and reads like a model answer.
  • Hand-evaluations (like power 2 3 or hcf 12 18) must shrink visibly each step; the marker checks the base case is reached.

Self-check

  1. Rewrite grade from §2.3 using if-then-else only. Which version is clearer and why?
  2. What is the type of add 1 if add :: Int -> Int -> Int?
  3. Why must s in heronArea be in a where block rather than computed three times inline? (Two reasons: readability and sharing.)
  4. Evaluate hcf 48 18 by hand.
  5. State the difference between div and /, including the type classes they belong to.