Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
pp:2025:l11 [2025/05/18 13:01] cata_chiru |
pp:2025:l11 [2025/05/18 13:35] (current) cata_chiru [11.3. Nice to read] |
||
|---|---|---|---|
| Line 97: | Line 97: | ||
| Applicates, as monads, are used preponderantly for type construction and validation. | Applicates, as monads, are used preponderantly for type construction and validation. | ||
| - | 1. For the first task we will want to validate a database of users. | + | 5. For the first task we will want to validate a database of users. |
| Being given the following data types: | Being given the following data types: | ||
| Line 114: | Line 114: | ||
| </code> | </code> | ||
| - | 1.1. Create the instance of Applicative for Validation. | + | 5.1. Create the instance of Applicative for Validation. |
| - | 1.2. Create functions to validate each attribute of a user. | + | 5.2. Create functions to validate each attribute of a user. |
| <code haskell> | <code haskell> | ||
| Line 130: | Line 130: | ||
| Balance can also be negative. | Balance can also be negative. | ||
| - | 1.3. Make use of the above functions, and the functions from Applicative, as well as infixed fmap ''(<$>)'' to create a validation function for the user. | + | 5.3. Make use of the above functions, and the functions from Applicative, as well as infixed fmap ''(<$>)'' to create a validation function for the user. |
| <code haskell> | <code haskell> | ||
| Line 136: | Line 136: | ||
| </code> | </code> | ||
| - | 1.4 Create unpackUser that takes a tuple and returns a User: | + | 5.4 Create unpackUser that takes a tuple and returns a User: |
| <code haskell> | <code haskell> | ||
| Line 142: | Line 142: | ||
| </code> | </code> | ||
| - | 1.5 Being given the following list of user data: | + | 5.5 Being given the following list of user data: |
| <code haskell> | <code haskell> | ||
| Line 156: | Line 156: | ||
| </code> | </code> | ||
| - | 1.6 Filter the users with a negative balance. | + | 5.6 Filter the users with a negative balance. |
| <code haskell> | <code haskell> | ||
| filter_debtors :: BankAccount -> BankAccount | filter_debtors :: BankAccount -> BankAccount | ||
| + | </code> | ||
| + | |||
| + | 6. Recall what a parser is from the course lecture: | ||
| + | |||
| + | <code haskell> | ||
| + | import Data.Char | ||
| + | import Control.Applicative | ||
| + | |||
| + | data Expr = Var String | Val Int | Plus Expr Expr deriving Show | ||
| + | |||
| + | data Parser a = Parser (String -> [(a,String)]) | ||
| + | |||
| + | parse (Parser p) s = p s | ||
| + | |||
| + | instance Monad Parser where | ||
| + | -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b | ||
| + | mp >>= f = Parser $ \s -> | ||
| + | case parse mp s of | ||
| + | [] -> [] | ||
| + | [(v,r)] -> parse (f v) r | ||
| + | return x = Parser $ \s -> [(x,s)] | ||
| + | |||
| + | instance Applicative Parser where | ||
| + | af <*> mp = | ||
| + | do | ||
| + | f <- af | ||
| + | v <- mp | ||
| + | return $ f v | ||
| + | pure = return | ||
| + | |||
| + | instance Functor Parser where | ||
| + | fmap f mp = | ||
| + | do | ||
| + | x <- mp | ||
| + | return $ f x | ||
| + | |||
| + | |||
| + | charParser :: Char -> Parser Char | ||
| + | charParser c = Parser $ \s -> | ||
| + | case s of | ||
| + | [] -> [] | ||
| + | (x:xs) -> if (x == c) then [(x,xs)] else [] | ||
| + | |||
| + | predicateParser :: (Char -> Bool) -> Parser Char | ||
| + | predicateParser p = Parser $ \s -> | ||
| + | case s of | ||
| + | [] -> [] | ||
| + | (x:xs) -> if p x then [(x,xs)] else [] | ||
| + | |||
| + | |||
| + | |||
| + | </code> | ||
| + | |||
| + | 6.1 Try to understand and reimplement the instances for Functor, Applicative and Monad for Parser yourself. | ||
| + | |||
| + | 6.2 Using the definitions above and functions from Data.Char [5], implement letter - that parses one letter of the input, and digit - that parses one digit (given as a char) of the input. | ||
| + | |||
| + | <code haskell> | ||
| + | letter :: Parser Char | ||
| + | letter = undefined | ||
| + | |||
| + | digit :: Parser Char | ||
| + | digit = undefined | ||
| + | </code> | ||
| + | |||
| + | 6.3 Use letter, digit and functions from the classes studied in this laboratory to define letterDigit that parses one letter and one digit one after the other: | ||
| + | |||
| + | <code haskell> | ||
| + | letterDigit :: Parser (Char,Char) | ||
| + | letterDigit = undefined | ||
| + | |||
| + | positive_parse_ex = parse letterDigit "a1b2c3" -- by calling this in the command line we should get [(('a','1'),"b2c3")] | ||
| + | negative_parse_ex = parse letterDigit "aa2a" -- by calling this in the command line we should get [] | ||
| </code> | </code> | ||
| Line 173: | Line 246: | ||
| 4. https://www.youtube.com/watch?v=FLAPIgvlVnE&t=1945s&ab_channel=JamesHobson | 4. https://www.youtube.com/watch?v=FLAPIgvlVnE&t=1945s&ab_channel=JamesHobson | ||
| + | 5. [Data.Char Library](https://hackage.haskell.org/package/base-4.21.0.0/docs/Data-Char.html) | ||