Skip to content

Commit

Permalink
Prepare course 5
Browse files Browse the repository at this point in the history
  • Loading branch information
smelc committed Sep 26, 2024
1 parent d8a54b0 commit 614f80d
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 149 deletions.
47 changes: 0 additions & 47 deletions slides/Course03.hs
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,6 @@ balance' = foldr (\op soFar -> toInt op + soFar) 0
where
toInt = \case Debit x -> -x; Credit x -> x

class Functor f => Applicative f where
-- | Wraps a function in the functor
pure :: a -> f a

-- |
(<*>) :: f (a -> b) -> f a -> f b

-- | @initials "Clément" "Hurlin"@ returns "CH"
initials :: String -> String -> String
initials firstname lastname =
Expand All @@ -147,43 +140,3 @@ mkEmail firstName lastName domain ext =
let right = domain ++ "." ++ ext in
left ++ "@" ++ right

mkEmailSafe :: String -> String -> String -> Either String String
mkEmailSafe user host ext =
checkUsername user
>>= \(username :: String) ->
checkExt ext
>>= \(extension :: String) ->
Right (username ++ "@" ++ host ++ "." ++ extension)
where
checkUsername :: String -> Either String String
checkUsername s =
if all isLower s
then Right s
else Left ("Username should be lowercase, but found: " ++ s)
checkExt :: String -> Either String String
checkExt "com" = Right "com"
checkExt "fr" = Right "fr"
checkExt s =
Left ("Unexpected extension: "
++ show s
++ ". Expected one of: [\"com\", \"fr\"]")

mkEmailSafe' :: String -> String -> String -> Either String String
mkEmailSafe' user host ext = do
username <- checkUsername user
extension <- checkExt ext
pure (username ++ "@" ++ host ++ "." ++ extension)
where
checkUsername :: String -> Either String String
checkUsername s =
if all isLower s
then Right s
else Left ("Username should be lowercase, but found: " ++ s)
checkExt :: String -> Either String String
checkExt "com" = Right "com"
checkExt "fr" = Right "fr"
checkExt s =
Left ("Unexpected extension: "
++ show s
++ ". Expected one of: [\"com\", \"fr\"]")

27 changes: 27 additions & 0 deletions slides/Course05.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
module Course05 where

import Control.Monad.IO.Class
import Data.Char
import Data.Word
import Prelude hiding ((==), Bounded, Enum, Eq, Ordering, Show)

mkEmailSafe :: String -> String -> String -> Either String String
mkEmailSafe user host ext =
checkUsername user
>>= \(username :: String) ->
checkExt ext
>>= \(extension :: String) ->
Right (username ++ "@" ++ host ++ "." ++ extension)

checkUsername :: String -> Either String String
checkUsername s | all isLower s = Right s
| otherwise = Left ("Username should be lowercase, but found: " ++ s)
checkExt :: String -> Either String String
checkExt =
\case
"com" -> Right "com"
"fr" -> Right "fr"
s -> Left ("Unexpected extension: "
++ show s
++ ". Expected one of: [\"com\", \"fr\"]")

mkEmailSafe' :: String -> String -> String -> Either String String
mkEmailSafe' user host ext = do
username <- checkUsername user
extension <- checkExt ext
pure (username ++ "@" ++ host ++ "." ++ extension)

99 changes: 0 additions & 99 deletions slides/course-03.md
Original file line number Diff line number Diff line change
Expand Up @@ -563,105 +563,6 @@ Its syntax is: `let varName = expression in expression`
- What is the type of `mkEmail`?
- How does inference work?

---

# More composition

```bash
> import Data.Functor
> :type (<&>)
(<&>) :: Functor f => f a -> (a -> b) -> f b
> :type fmap
fmap :: Functor f => (a -> b) -> f a -> f b
```

- Given an element of type `a` wrapped in something (`f`), and a function from `a` to `b`, apply the function inside the wrapping.

- What can be `f`?

???

```bash
> import Data.List.Extra
> :type upper
upper :: String -> String
> applyUpper = fmap upper
> applyUpper (Just "foo")
> applyUpper (Right "foo" :: Either Int String)
```

???

If done at this point and time remains:

- Explain `foldr`
- Explain things defined in terms of `foldr`:
- `sum`
- `and :: [Bool] -> Bool`
- `any :: (a -> Bool) -> [a] -> Bool`

---

# More composition: monads

```bash
> :type (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
```

```hs
mkEmailSafe :: String -> String -> String -> Either String String
mkEmailSafe user host ext =
checkUsername user
>>= \(username :: String) ->
checkExt ext
>>= \(extension :: String) ->
Right (username ++ "@" ++ host ++ "." ++ extension)
where
checkUsername :: String -> Either String String
checkUsername s =
if all isLower s
then Right s
else Left ("Username should be lowercase, but found: " ++ s)
checkExt :: String -> Either String String
checkExt "com" = Right "com"
checkExt "fr" = Right "fr"
checkExt s =
Left ("Unexpected extension: "
++ show s
++ ". Expected one of: [\"com\", \"fr\"]")
```

---

# User friendly monads: the `do` notation

```bash
> :type (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
```

```hs
mkEmailSafe' :: String -> String -> String -> Either String String
mkEmailSafe' user host ext = do
username <- checkUsername user
extension <- checkExt ext
pure (username ++ "@" ++ host ++ "." ++ extension)
where
checkUsername :: String -> Either String String
checkUsername s =
if all isLower s
then Right s
else Left ("Username should be lowercase, but found: " ++ s)
checkExt :: String -> Either String String
checkExt "com" = Right "com"
checkExt "fr" = Right "fr"
checkExt s =
Left ("Unexpected extension: "
++ show s
++ ". Expected one of: [\"com\", \"fr\"]")
```

<!-- Machinery for making the snippets valid, not shown, only
used by exdown (see check.sh).
Expand Down
20 changes: 19 additions & 1 deletion slides/course-04.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,25 @@ class Functor f where
fmap :: (a -> b) -> f a -> f b
```

- Give instances:
```bash
> import Data.List.Extra
> :type upper
upper :: String -> String
> applyUpper = fmap upper
> :type applyUpper
applyUpper :: Functor f => f String -> f String
```

--

```bash
> applyUpper (Just "foo")
> applyUpper (Right "foo" :: Either Int String)
```

--

- Instances we've seen before:
- `Maybe a`
- `[a]`

Expand Down
31 changes: 31 additions & 0 deletions slides/course-05.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Mastering the Type System</title>
<meta charset="utf-8">
<style>
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz);
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic);

body { font-family: 'Droid Serif'; }
h1, h2, h3 {
font-family: 'Yanone Kaffeesatz';
font-weight: normal;
}
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; }
.remark-inline-code { background-color: #F0F0F0; }
</style>
</head>
<body>
<!-- See https://github.com/gnab/remark/wiki for guidance -->
<script src="https://remarkjs.com/downloads/remark-latest.min.js">
</script>
<script>
var slideshow = remark.create({
sourceUrl: 'course-05.md'
});
</script>
</body>
</html>

44 changes: 42 additions & 2 deletions slides/course-05.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Clément Hurlin
module Course05 where
import Control.Monad.IO.Class
import Data.Char
import Data.Word
import Prelude hiding ((==), Bounded, Enum, Eq, Ordering, Show)
```
Expand All @@ -39,7 +40,7 @@ class Course05 {
In this course:

<center>
Advanced Type System
Mastering the Type System
</center>

<br/>
Expand All @@ -48,9 +49,48 @@ In this course:

# Monads

```bash
> :type (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
```

```hs
mkEmailSafe :: String -> String -> String -> Either String String
mkEmailSafe user host ext =
checkUsername user
>>= \(username :: String) ->
checkExt ext
>>= \(extension :: String) ->
Right (username ++ "@" ++ host ++ "." ++ extension)

checkUsername :: String -> Either String String
checkUsername s | all isLower s = Right s
| otherwise = Left ("Username should be lowercase, but found: " ++ s)
checkExt :: String -> Either String String
checkExt =
\case
"com" -> Right "com"
"fr" -> Right "fr"
s -> Left ("Unexpected extension: "
++ show s
++ ". Expected one of: [\"com\", \"fr\"]")
```
---

# Type Applications
# User friendly monads: the `do` notation

```bash
> :type (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
```

```hs
mkEmailSafe' :: String -> String -> String -> Either String String
mkEmailSafe' user host ext = do
username <- checkUsername user
extension <- checkExt ext
pure (username ++ "@" ++ host ++ "." ++ extension)
```

---

Expand Down
1 change: 1 addition & 0 deletions tn-fp-course.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ library slides
Course02
Course03
Course04
Course05

executable TP1.hs
import: common-all
Expand Down

0 comments on commit 614f80d

Please sign in to comment.