Skip to content

Commit

Permalink
Various enhancements and additions
Browse files Browse the repository at this point in the history
  • Loading branch information
smelc committed Jan 15, 2024
1 parent 5f8bcc9 commit d497134
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 5 deletions.
19 changes: 19 additions & 0 deletions slides/Course03.hs
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,22 @@ mkEmailSafe user host ext =
++ 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\"]")

29 changes: 29 additions & 0 deletions slides/Course04.hs
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,32 @@ data Interval a = Interval {
}
deriving Functor

-- | @makeURL "http" "google.fr" "search/advanced"@ returns
-- @"http://www.google.fr/search/advanced"@
makeURL :: String -> String -> String -> String
makeURL = undefined

newtype Protocol = Protocol String

newtype Hostname = Hostname String

newtype Segments = Segments [String]

makeURL' :: Protocol -> Hostname -> Segments -> String
makeURL' = undefined

data User = User { name :: String, avatar :: FilePath, id :: Int }

-- | @authenticate user password@ tries to authenticate @user@ with @password@
authenticate :: User -> String -> Bool
authenticate = undefined

data Guest
data Authenticated

-- @type@ defines aliases (shortcuts)
type UserWithAuthStatus a = User

authenticate' :: User -> String -> UserWithAuthStatus Authenticated
authenticate' = undefined

1 change: 1 addition & 0 deletions slides/course-01.md
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ Property-based testing:

# Recommended Reading

- https://learnyouahaskell.github.io/chapters.html
- http://book.realworldhaskell.org/read/getting-started.html

<!-- Machinery for making the snippets valid, not shown, only
Expand Down
36 changes: 33 additions & 3 deletions slides/course-03.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,8 @@ Functional toolbox:

# Recommended Reading

- http://learnyouahaskell.com/syntax-in-functions
- http://learnyouahaskell.com/higher-order-functions
- https://learnyouahaskell.github.io/syntax-in-functions.html
- https://learnyouahaskell.github.io/higher-order-functions.html

---

Expand Down Expand Up @@ -531,7 +531,7 @@ If done at this point and time remains:

---

# More composition
# More composition: monads

```bash
> :type (>>=)
Expand Down Expand Up @@ -561,6 +561,36 @@ mkEmailSafe user host ext =
++ ". 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
76 changes: 75 additions & 1 deletion slides/course-04.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,74 @@ frequency :: [(Int, Gen a)] -> Gen a

---

# `newtype`

```hs
-- | @makeURL "http" "google.fr" "search/advanced"@ returns
-- @"http://www.google.fr/search/advanced"@
makeURL :: String -> String -> String -> String
makeURL = undefined
```

<center>
What's error prone about this function for callers?
</center>

--

```hs
newtype Protocol = Protocol String

newtype Hostname = Hostname String

newtype Segments = Segments [String]

makeURL' :: Protocol -> Hostname -> Segments -> String
makeURL' = undefined
```

`newtype`:
* Cost-free (runtime) disambiguation 💪
* ⚠️ It's just names! ⚠️

---

# Phantom Types

```hs
data User = User { name :: String, avatar :: FilePath, id :: Int }

-- | @authenticate user password@ tries to authenticate @user@ with @password@
authenticate :: User -> String -> Bool
authenticate = undefined
```

<center>
How to model that a user is authenticated to the system?
</center>

--

```hs
data Guest
data Authenticated

-- @type@ defines aliases (shortcuts)
type UserWithAuthStatus a = User

authenticate' :: User -> String -> UserWithAuthStatus Authenticated
authenticate' = undefined
```

--

Phantom types:

* Use type parameters as markers to distinguish data
* Could you do that in Java?

---

# Recap

Typeclasses:
Expand All @@ -409,10 +477,16 @@ Typeclasses:

# Recommended reading

- http://learnyouahaskell.com/types-and-typeclasses#typeclasses-101
- https://learnyouahaskell.github.io/types-and-typeclasses.html#typeclasses-101
- http://book.realworldhaskell.org/read/using-typeclasses.html
- https://wiki.haskell.org/Typeclassopedia

---

# Type Applications

TODO for next year

<!-- Machinery for making the snippets valid, not shown, only
used by exdown (see check.sh).
Expand Down
3 changes: 2 additions & 1 deletion tps/TP1.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
-- Load me in the REPL with: cabal repl TP1.hs, then use :r to reload the code upon changing

--
-- In this file, you need to replace the @undefined@ calls by real code
-- In this file, you need to replace the @undefined@ calls by real code.
--
-- Resource for the syntax of functions: https://learnyouahaskell.github.io/syntax-in-functions.html

module Main where

Expand Down
11 changes: 11 additions & 0 deletions tps/TP5.hs
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,14 @@ main = do
html "<h1>Hello</h1>"
where
port :: Int = 3000

data User = User { name :: String, avatar :: FilePath, id :: Int }

-- | @authenticate user password@ tries to authenticate @user@ with @password@
authenticate :: User -> String -> UserWithAuthStatus Authenticated
authenticate = undefined

data Guest
data Authenticated

type UserWithAuthStatus a = User

0 comments on commit d497134

Please sign in to comment.