{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE MultiParamTypeClasses #-} class MonadTrans t where lift :: (Monad m) => m a -> (t m) a -- t is monad transformer if -- for any monad m, we have a monad (t m) data Identity a = Id {runId :: a} instance Functor Identity where fmap f (Id x) = Id (f x) instance Applicative Identity where instance Monad Identity where return :: a -> Identity a return = Id (>>=) :: Identity a -> (a -> Identity b) -> Identity b (Id x) >>= f = f x type State s a = StateT s Identity a -- s -> (a, s) instance (Functor m) => Functor (StateT s m) where fmap :: (a -> b) -> StateT s m a -> StateT s m b fmap f (StateT g) = StateT $ \ x -> fmap (\ (y, s) -> (f y, s)) (g x) -- :: m (b, s) -- g :: s -> m (a, s) -- g x :: m (a, s) -- fmap_m :: (a -> b) -> m a -> m b -- fmap_m :: ((a, s) -> (b, s)) -> m (a, s) -> m (b, s) instance (Applicative m) => Applicative (StateT s m) where instance (Monad m) => Monad (StateT s m) where return :: a -> StateT s m a return x = StateT $ \ s -> return (x, s) -- :: m (a, s) (>>=) :: StateT s m a -> (a -> StateT s m b) -> StateT s m b (StateT g) >>= f = StateT $ \ x -> g x >>= (\ (y, z) -> let (StateT h) = f y in h z ) -- :: (a, s) -> m (b, s) -- y :: a -- z :: s -- x :: s -- g :: s -> m (a, s) -- g x :: m (a, s) -- f :: a -> StateT s m b -- h :: s -> m (b, s) instance MonadTrans (StateT s) where lift :: (Monad m) => m a -> StateT s m a lift y = StateT $ \ s -> y >>= (\ x -> return (x, s)) -- do{ x <- y; return (x, s)} -- :: m (a, s) parse :: String -> Parser a -> Maybe (a, String) parse s p = runStateT p s class Monad m => MonadState s m where get :: m s put :: s -> m () instance Monad m => MonadState s (StateT s m) where get :: (StateT s m) s get = StateT $ \ s -> return (s, s) -- :: m (s, s) put :: s -> (StateT s m) () put x = StateT $ \ s -> return ((), x) -- :: m ((), s) type Parser a = StateT String Maybe a -- String -> Maybe (a, String) eof :: Parser () eof = do s <- get if null (s :: String) then return () else mzero item :: Parser Char item = do s <- get case s of [] -> mzero x:xs -> do put xs return x -- Monoid of monads class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a instance MonadPlus Maybe where mzero :: Maybe a mzero = Nothing mplus :: Maybe a -> Maybe a -> Maybe a Nothing `mplus` x = x Just x `mplus` y = Just x -- Our first example of a monad transformer. -- It gives us ability to add state to an existing -- monad. data StateT s m a = StateT {runStateT :: s -> m (a, s)} instance (MonadPlus m) => MonadPlus (StateT s m) where mzero :: StateT s m a mzero = StateT $ \ s -> mzero -- :: m (a, s) mplus :: StateT s m a -> StateT s m a -> StateT s m a (StateT g1) `mplus` (StateT g2) = StateT $ \ s -> g1 s `mplus` g2 s -- :: m (a, s) (<|>) :: Parser a -> Parser a -> Parser a (<|>) = mplus sat :: (Char -> Bool) -> Parser Char sat f = do x <- item if f x then return x else mzero -- Parse a charactor. char :: Char -> Parser Char char c = sat (\ x -> x == c) -- Recursive parser combinators. Parse an input string -- String = [Char] string :: String -> Parser String string [] = return [] string (x:xs) = do y <- char x ys <- string xs return (y:ys) -- Apply a parser zero or more times. many :: Parser a -> Parser [a] many p = do{ x <- p; xs <- many p; return (x:xs)} <|> return [] -- Apply a parser one or more times. many1 :: Parser a -> Parser [a] many1 p = do x <- p xs <- many p return (x:xs) -- sepBy p sep parses zero or more occurrences of p, -- separated by sep. Returns a list of values returned by p. sepby :: Parser a -> Parser b -> Parser [a] p `sepby` sep = do{ x <- p; xs <- many (sep >> p); return (x:xs) } <|> return [] sepby1 :: Parser a -> Parser b -> Parser [a] p `sepby1` sep = do{ x <- p; xs <- many (sep >> p); return (x:xs) } -- A simple CSV parser csv :: Parser [[String]] csv = many line line :: Parser [String] line = do cs <- content `sepby1` comma (char '\n' >> return ()) <|> eof return cs comma :: Parser Char comma = char ',' -- parse a charactor as long as it is not one of the charactor -- in the input string. noneOf :: [Char] -> Parser Char noneOf str = do c <- item if elem c str then mzero else return c content :: Parser String content = many1 (noneOf ",;.\n")