Add the rest of university notes

This commit is contained in:
John Gatward committed 2026-10-04 14:02:35 +01:00
1 parent c1b84c7f7d
commit d0f27f276b
366 files changed
+9844 -110

No files matched your search

@@ -0,0 +1,88 @@
# Monad Revision
You can think of a monad as a container for a data type
If $M$ is a monad, that means an element of $M$: $M_a$ is some sort of container where $a$ is any datatype
One of the purposes of the `do` notation is to operate on the whole data structure by specify operations that must apply to each of the elements in the data structure, without having to specify the whole structure.
$$
M_a=\{x_1, x_2, x_3,...\}
$$
```haskell
do x <- m
let y = x ** 2 + 7
return y
```
This extracts an element of type $a$ from $m$, squares and adds 7, and returns the new values as the data structure. Now $M$ is
$$
M_b=\{y_1, y_2, y_3, \ldots\}\\or\\M=\{x_1^2+7, x_2^2+7, x_3^2+7, \ldots\}
$$
The above can be written as a functor
```haskell
fmap (\x -> x**2+7) m
```
Monads have more functionality than functors though
If $x$ is an element of $a$ or $x :: a$
```haskell
x :: a
return x
-- we can also write
pure x
```
Monads can have containers within containers
Assume we have function `makeBlob` that maps every element of $a$ to an element of $M_b$
```haskell
makeBlob :: a -> Mb
makeBlob x1 = do x <- m
y <- makeBlob x
return y
-- this can be done instead with the bind operator
m >>= makeBlob
(>>=) :: Ma -> (a -> Mb) -> Mb
```
## The IO Monad
```haskell
square :: Int -> Int
square x = x*x
getInt :: IO Int
getInt = do putStrLn "Enter a number: "
s <- getLine -- getLine :: IO String
return (read s :: Int) --read :: String -> Int
squareIO :: IO Int
squareIO = do x <- getInt
let y <- square x
return y
-- as squareIO :: IO Int, returning y prints it out
squareIO :: IO () -- unit type, with only one element, also called ()
squareIO = do x <- getInt
let y <- square x
putStrLn("The square " ++ (show x) ++ " is " (show y))
return () --return unit type
-- in this case we dont even need return () as
-- putStrLn :: IO ()
--recursively asks for list unless 0 entered
getList :: IO [Int]
getList = do x <- getInt
if x == 0 then return []
else do
xs <- getList
return (x:xs)
```