"state": {
"type": "markdown",
"state": {
- "file": "Functional Programming/Functional Programming Introduction.md",
+ "file": "Functional Programming/Lecture 2.md",
"mode": "source",
"source": false,
"backlinks": true,
}
},
"icon": "lucide-file",
- "title": "Functional Programming Introduction"
+ "title": "Lecture 2"
}
}
]
}
],
"direction": "horizontal",
- "width": 300
+ "width": 300,
+ "collapsed": true
},
"right": {
"id": "52c8cd2985704b8e",
},
"active": "d417039fb31acf08",
"lastOpenFiles": [
+ "Functional Programming/Functional Programming Introduction.md",
+ "Functional Programming/Lecture 2.md",
"Ruxi.md",
"Pasted image 20250207160807.png",
"Documents Archive Organisational Notes.md",
"Recontextualising Creativity/RC Reading Responses/Reading Response Week 6",
"PoC/PoC Teamwork/PoC Coaching 5-12-2024.md",
"PoC/PoC Research (Poster)/PoC Poster Overview.md",
- "PoC/PoC Research (Poster)/PoC Poster References.md",
- "Freedom by Angela Merkel/Notes on Freedom by Angela Merkel.md"
+ "PoC/PoC Research (Poster)/PoC Poster References.md"
]
}
\ No newline at end of file
--- /dev/null
+The list of values from i to j is written:
+[i..j]
+
+- [1..10] = [1,2,3,4,5,6,7,8,9,10]
+- [1,3..10] = [1,3,5,7,9]
+- [42..42] = [42]
+- [10..1] = []
+- [10,8..1] = [10,8,6,4,2]
+
+# List Comprehensions
+`[ x * x | x <- [1..5] ] = [1,4,9,16,25]`
+x <- [1..5] is the generator
+You can have multiple generators.
+
+the order of the generator matters -> it won't change the result but the order of the result. The outer loop will be the first list, the inner one the second list etc. etc.
+
+Later generators can depend on previous ones.
+`[10 * x + y | x <- [1..3], y <- [x..3] ]`
+
+We can select only elements that satisfy a boolean predicate.
+`[x | x <- [1..10] , even x ]` even is called a 'guard'. A guard must return type 'Bool'.
+
+```haskell
+addMod3Is2 :: [Int] -> [Int]
+addMod3Is2 x = [a + 3 | a <- x , x `mod` 3 === 2]
+
+-- the `` simply mean that you want to use infix notation
+
+concat :: [[Int]] -> [Int]
+concat xss = [y | x <- xss, y <- x]
+```
+
+# Defining and Testing Functions
+## Pattern Matching
+We can define functions by case analysis using pattern matching:
+
+```haskell
+not :: Bool -> Bool
+not True = False
+not False = True
+```
+
+One of the most powerful ones, will have to use it a lot.
+
+A pattern var matches any value that didn't match the prev patterns:
+
+```haskell
+
+rank 1 = "first"
+rank 2 = "second"
+rank 3 = "third"
+rank n = show n ++ "th"
+```
+
+A wildcard `_` is like a pattern value for which you don't care about the value.
+
+can even be used for curried functions, wonderful
+```haskell
+xor :: Bool -> Bool -> Bool
+xor True False = True
+xor False True = True
+xor _ _ = False
+```
+
+The order does matter. Haskell will use the first clause that matches.
+
+infix operations such as (+), (-), (!!) are just regular haskell functions
+- name must consist of special chars only
+must be parentesized when appearing by themselves
+Can be used as normal:
+`(+) 1 1 == 1 + 1`
+
+lists in haskell are singly linked list
+
+```haskell
+isEmpty :: [a] -> Bool
+isEmpty [] = True
+isEmpty (x:xs) = False
+```
+Any list is either [] or x:xs
+`[1,2,3]` is sugar for `1:2:3:[]`, this is important so that technically 'single' item lists, are actually two element lists and therefore match (x:xs) anyway.
+
+## Using Guards
+we can use guards to add boolean conditions to a clause
+
+```haskell
+signum x
+ | x < 0 = -1
+ | x == 0 = 0
+ | otherwise = 1
+```
+
+Guards `| b` appear after the patterns (and before =)
+The condition be should be type bool
+otherwise is defined to be always True
+
+mixing guards and pattern matching
+
+```haskell
+capitalize :: String -> String
+capitalize (c : cs)
+ | isLower c = (toUpper c) : cs
+capitalize cs = cs
+```
+
+will continue until it finds one that matches
+
+## Recursion
+
+there is the 'error' function. another reason why haskell is partial.
+cannot call a function inside a pattern, typically you have to do guards.
+
+a 4 step plan for implementing a (recursive) function\
+- write down the type
+- enumerate the cases
+- define the base cases
+- define the recursive cases
+
+## Polymorphic Types
+
+we don't want multiple function definitions for different types, for length we want more than just [Int] for example
+so not
+`length :: [Int] -> Int`, but something more general
+sure sometimes we also want to restrict it a bit.
+
+length function is easy, for example:
+`length :: [a] -> Int`, we don't have to define it, since haskell can infer
+
+## Type Classes
+What should be the type of double x = x + x
+Int -> Int , does not include floats etc.
+but a -> a doesn't work, doesn't work for bools for example
+Solution, Add a constraint:
+```haskell
+-- Num a =>
+
+double :: Num a => a -> a
+-- I assume you can find these groups in the standard lib.
+
+-- the num thing
+-- num ia an example of a type class, a collection of types that support a common interface
+class Num a where
+ (+) :: a -> a -> a
+ (-) :: a -> a -> a
+ (*) :: a -> a -> a
+ negate :: a -> a
+ abs :: a -> a
+ fromInteger :: Integer -> a
+```
+
+you cannot use the 'num' type on its own, its a constraint not a type itself, so you can't have `[Num]`
+
+There is the `Eq` class.
+`Ord` class, things that can be ordered. Subclass of `Eq`