# Expressions, Types and Functions — Haskell

Source: https://www.geekswithgeeks.com/en/haskell/f-basics

> Write functions with type signatures, guards, where and let, and use operators.

## Everything is an expression

A Haskell program is built from **expressions** and **definitions**. Basic types include `Int` (fixed-size), `Integer` (arbitrary precision), `Double`, `Bool`, `Char` and `String` (a list of `Char`; real projects use `Text`). Write a **type signature** above each top-level function: `withGst :: Int -> Int`. A function of several arguments has type `Int -> Int -> Int`: functions are **curried**, taking one argument at a time, so **partial application** (`add 5`) produces a new function. Application binds tighter than any operator: `f x + 1` means `(f x) + 1`. **`if then else`** is an expression and always has an `else`. **Guards** (`| condition = result`) choose between cases and **`otherwise`** catches the rest. **`where`** defines helper values after a function, and **`let ... in`** defines them before an expression. Operators are functions: `(+) 2 3`, and any function can be used infix with backticks, as in `` 7 `div` 2 ``. **Sections** partially apply operators: `(* 2)`, `(subtract 1)`. Numeric literals are polymorphic, and conversions are explicit: `fromIntegral` converts integers to other numeric types. Integer division uses `div` and `mod`; `/` is for fractional types.

## Functions with guards and where

Prices in paise to avoid floating-point rounding.

```haskell
-- Integer paise avoid floating-point surprises with money
withGstPaise :: Int -> Int
withGstPaise paise = paise + (paise * 18 + 50) `div` 100   -- rounds to the nearest paisa

shippingFee :: Int -> Bool -> Int
shippingFee totalPaise express
  | totalPaise >= 100000 = 0
  | express              = 9900
  | otherwise            = 4900

bmiCategory :: Double -> Double -> String
bmiCategory weightKg heightM
  | bmi < 18.5 = "underweight"
  | bmi < 25   = "normal"
  | otherwise  = "overweight"
  where
    bmi = weightKg / (heightM * heightM)

average :: [Int] -> Double
average [] = 0
average xs = fromIntegral (sum xs) / fromIntegral (length xs)

addTax :: Int -> Int -> Int
addTax rate amount = amount + amount * rate `div` 100

main :: IO ()
main = do
  print (withGstPaise 10000)          -- 11800
  print (shippingFee 20000 True)      -- 9900
  putStrLn (bmiCategory 68 1.75)      -- normal
  print (7 `div` 2, 7 `mod` 2)        -- (3,1)
  let gst18 = addTax 18               -- partial application
  print (map gst18 [100, 250])        -- [118,295]
```

## Write the type first

Writing the type signature before the body clarifies what a function should do, gives better error messages, and lets you use typed holes (`_`) so GHC tells you what type is needed at that spot.

**Quiz:** What is the type of `addTax 18` if `addTax :: Int -> Int -> Int`?

- [ ] Int
- [ ] Int -> Int -> Int
- [x] Int -> Int
- [ ] It is a type error

*Answer:* Int -> Int. Curried functions return a new function when partially applied.
