<jupyter_start><jupyter_text>Haskell Basics for Functional Programming *Some snippets in this notebook are taken from BLG458E Functional Programming course slides which can be accessed through the following link: https://www.slideshare.net/uyar/tag/blg458e*  DefinitionsDefinitions associate an identifier(name) with a value of a specific type  **Format:**  ```haskellname :: typename = expression```*Frequently used types: Int, Float, String, Char, Bool, Double, Integer*<jupyter_code>age :: Int      -- age is an integer
age = 20        -- age is equal to 20

name :: String  -- name is a string
name = "Bob"    -- name is equal to Bob

gpa :: Float    -- gpa is a float
gpa = 3.78      -- gpa is equal to 3.78
age
name
gpa<jupyter_output><empty_output><jupyter_text>**Example**  Calculate circumference of a circle whose radius is 7.2<jupyter_code>radius :: Float
radius = 7.2

circumference :: Float
circumference = 2 * 3.14159 * radius

circumference<jupyter_output><empty_output><jupyter_text>Local DefinitionsWe can also define identifiers locally *which can only used inside a block*  **Format:**  ```haskellname = expression    where    name1 :: type1    name1 = expression1      name2 :: type2    name2 = expression2       ...```     Note: Haskell can infer the types of identifiers, so name::type parts can be left out. **Example**  Calculate BMI of a person whose weight is 78 kg and height is 1.82 m<jupyter_code>bmi :: Float
bmi = weight / (height * height)    -- we'll define weight and height inside where
  where
    weight = 78    -- Haskell infers the type of weight and height
    height = 1.82   

bmi
weight  -- locally-defined identifiers aren't accessible outside of their scope<jupyter_output><empty_output><jupyter_text>Functions**Definition:**  ```haskellfunctionName :: param1Type -> param2Type -> ... -> paramkType -> resultTypefunctionName param1 param2 ... paramk = result```For example, you can call functions like this:  `functionName p1 p2 p3` where p1, p2, and p3 represent parameters of the function<jupyter_code>square :: Int -> Int      -- parameter is of type Int and result is also of Type Int
square x = x * x          -- parameter is x, and result is x^2
square 7<jupyter_output><empty_output><jupyter_text>Local Function DefinitionsYou can define functions locally as well using *where* keyword **Example**  Let's write a function to calculate a3 - b3<jupyter_code>differenceOfCubes :: Int -> Int -> Int
differenceOfCubes a b = cube a - cube b
  where
    cube :: Int -> Int
    cube a = a * a * a
differenceOfCubes 5 3<jupyter_output><empty_output><jupyter_text>Prefix vs Infix Functions can be called in infix format using backticks.  For example you can call mod function using **mod 10 3** or **10 \`mod\` 3**<jupyter_code>mod 10 3
10 `mod` 3
mod 10 3 == 10 `mod` 3<jupyter_output><empty_output><jupyter_text>You can also use operators in prefix format.  All you need to do is put the operator inside paranthesis as follows:  *(/) 10 4*<jupyter_code>(/) 10 4<jupyter_output><empty_output><jupyter_text>Conditional StatementsIn order to write conditional statements, we can use *Guards*A guard is a boolean expression to check some condition**Format:**  ```haskellfunctionName :: p1Type -> p2Type -> ... -> pkType -> resultTypefunctionName p1 p2 .. pk  | guard1    = expression1  | guard2    = expression2  ...  | otherwise = expression```Return value is the expression of the first guard whose value is True.  If none of the guards is true, last expression (otherwise case) is returned.<jupyter_code>maxOfTwo :: Int -> Int -> Int
maxOfTwo a b
  | a >= b     = a
  | otherwise  = b
maxOfTwo 3 7<jupyter_output><empty_output><jupyter_text>We can also use if-then-else statements in order to write conditional statements.  **Format**  `if condition then x else y`<jupyter_code>if 12 > 5 then "12 is larger than 5" else "12 is not larger than 5"<jupyter_output><empty_output><jupyter_text>Error MessagesWe can use *error* keyword to define error messages.<jupyter_code>multiInverse :: Float -> Float
multiInverse a
  | a == 0    = error "Division by Zero!"
  | otherwise = 1 / a
multiInverse 5
multiInverse 0<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09423582874910308, 'fraction_numerical': 0.025831140875388663, 'mean_word_length': 4.131288343558282, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 58, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '346864', 'license': 'MIT', 'n_tokens_mistral': 1356, 'n_tokens_neox': 1241, 'n_words': 493, 'path': '1haskell_basics.ipynb', 'repo_name': 'mustafacobann/Functional-Programming', 'size': '4181'}