Edit this page Backlinks This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== Lab 10. Monads ====== ===== 10.0. Understanding Monads ===== A monad is an algebraic structure used to describe computations as sequences of steps, and to handle side effects such as state and IO. They also provide a clean way to structure our programs. \\ \\ In Haskell, Monads are defined as follows: <code haskell> class Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a </code> Recalling from this week's lecture, we know they (">>=") is the equivalent to our "join" operation which performs the sequencing. We also know that m is of kind * => *, hence is a container. <hidden> We also recall that **not all containers are monads** and that **all monads are functors**. </hidden> \\ Monads are already implemented in Haskell, 'Maybe' being one of them: <code haskell> instance Monad Maybe where mx >>= f = case mx of Just v -> f v Nothing -> Nothing return = Just </code> Do not forget about the syntactic sugar presented at lecture! ===== 10.1. Working with 'Maybe' ===== This section is meant to accommodate you to using Monads by playing around with an already implemented and familiar Monad: Maybe. We will work with the **Nat** data type that you already should be familiar with. Add the following lines to your code: <code haskell> data Nat = Zero | Succ Nat deriving Show fromInt :: Int -> Maybe Nat fromInt x | x < 0 = Nothing | otherwise = Just $ get x where get 0 = Zero get x = Succ (get (x-1)) </code> Every exercise will require you to implement extra functions which process Nat numbers such as adding or subtracting. Use fromInt function to manually test your solutions. **10.1.1** Implement the following adding and subtracting functions. Using Maybe allows us to easily treat the case of negative numbers. <code haskell> mminus :: Maybe Nat -> Maybe Nat -> Maybe Nat mminus m n = ??? mplus :: Maybe Nat -> Maybe Nat -> Maybe Nat mplus m n = ??? </code> **10.1.2** Implement multiplication (from scratch, do not use the already defined mplus). <code haskell> mmulti :: Maybe Nat -> Maybe Nat -> Maybe Nat mmulti m n = ??? </code> ===== 10.3. Implementing our 'Parser' ===== Firstly we need to understand the role of our parser. Given the type: <code haskell> data Expr = Atom Int | Var String | Plus Expr Expr deriving Show </code> our parser should be able to process the string: "1 + x + 2" \\ into and acceptable expression: Plus (Atom 1) $ Plus (Var "x") (Atom 2) Parsing a whole string at once is extremely inefficient and complex, hence we generally divide it into steps, such as: \\ parseAtom: "1 + x + 2" = (Atom 1, "+ x + 2") Also, we need to incorporate error-handling which we will represent using lists: the empty-list is an error, and the singleton list is a valid value containing it. Finally, parsing is not just limited to expressions, hence we need to build a general implementation. Now that we understand what we need to implement, this seems like a fitting job for Monads, as it incorporates sequencing, error-handling and modularity, which represent a perfect use for them. Firstly, add the following helper and imports to your code: <code haskell> import Data.Char import Control.Applicative -- helper to do the parsing for us data Parser a = Parser (String -> [(a,String)]) parse (Parser p) s = p s </code> **10.2.0** As as example, we can build a parser that always fails. Remember that we defined failures in parsing as empty lists. <code haskell> failParser :: Parser a failParser = Parser $ \s -> [] </code> **10.2.1** Now implement a parser that takes a char and will parse only that char. <code haskell> --If we need to parse 'A', we use this function to return us a parser that parses 'A'. charParser :: Char -> Parser Char charParser c = ??? </code> **10.2.2** Now implement a parser that takes a predicate of type (Char -> Bool) and parses the characters which satisfy the predicate. <code haskell> predicateParser :: (Char -> Bool) -> Parser Char predicateParser p = ??? </code>