Graham Hutton Haskell könyve es https://wiki.haskell.org/Typeclassopedia alapjan --------------------------------------------------------------- Funktorok --------------------------------------------------------------- incr :: [Int] -> [Int] incr [] = [] incr [n:ns] = [n+1:incr ns] sqr :: [Int] -> [Int] sqr [] = [] sqr [n:ns] = [n^2 : sqr ns] map :: (a -> b) [a] -> [b] map f [] = [] map f [x:xs] = [f x : map f xs] inc = map (+1) sqr = map (^1) class Functor f where fmap :: (a -> b) (f a) -> f b instace Functor [] where fmap = map instance Functor Maybe where fmap = ... :: Tree a = Node (Tree a) (Tree a) | Leaf a instance Functor Tree where fmap = ... Funktor törvények --------------------------------------------------------------- fmap id = id fmap (g . h) = famp g . fmap h Ezeket Cleanben nem lehet megadni, tehát elvileg meg tudunk adni olyan instance-okat is, melyekre ezek nem teljesülnek. Eredetileg kategóriaelmélet. Intuicio funktorokhoz: --------------------------------------------------------------- f a -> (a -> b) -> f b (apply the function inside the container) (a->b) -> (f a -> f b) lifting a function from normal types to f-types Tovabbi funktorok --------------------------------------------------------------- e-> (e,) Either e Nem funktor: ->e Monádok --------------------------------------------------------------- :: Expr = Val Int | Div Expr Expr eval :: Expr -> Int eval (Val n) = n eval (Div x y) = div (eval x) (eval y) Start = eval (Div (Val 1) (Val 0)) > Floating point exception -- probléma safediv :: Int -> Int -> Maybe Int safediv _ 0 = Nothing safediv n m = Just (n ‘div‘ m) eval :: Expr -> Maybe Int eval (Val n) = Just n eval (Div x y) = case eval x of Nothing = Nothing Just n = case eval y of Nothing = Nothing Just m = safediv n m Start = eval (Div (Val 1) (Val 0)) > Nothing -- ugyanaz a minta jelenik meg: (>>=) :: (Maybe a) (a -> Maybe b) -> Maybe b mx >>= f = case mx of Nothing = Nothing Just x = f x eval :: Expr -> Maybe Int eval (Val n) = Just n eval (Div x y) = eval x >>= \n -> eval y >>= \m -> safediv n m %%%%%%%%%%%%%%%%%%%%%%% % ELMAGYARAZNI^^^ %%%%%%%%%%%%%%%%%%%%%%% általános struktúra: m1 >>= \x1 -> m2 >>= \x2 -> . . . mn >>= \xn -> f x1 x2 ... xn jelölés Haskellben: do x1 <- m1 x2 <- m2 . . . xn <- mn f x1 x2 ... x eval :: Expr -> Maybe Int eval (Val n) = Just n eval (Div x y) = do n <- eval x m <- eval y safediv n m class Monad m where return :: a -> m a (>>=) :: (m a) (a -> m b) -> m b instance Monad Maybe where -- (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b Nothing >>= _ = Nothing (Just x) >>= f = f x instance Monad [] where -- (>>=) :: [a] -> (a -> [b]) -> [b] xs >>= f = [y | x <- xs, y <- f x] pairs :: [a] -> [b] -> [(a,b)] pairs xs ys = do x <- xs y <- ys return (x,y) > pairs [1,2] [3,4] [(1,3),(1,4),(2,3),(2,4)] %%%%%%%%%%%%%%%%%%%%%%% % ELMAGYARAZNI^^^ %%%%%%%%%%%%%%%%%%%%%%% State monad --------------------------------------------------------------- :: State = Int :: ST a :== State -> (State, a) doboz, egy state bemenet, ket kimenet masik doboz, ha van bemenet is Char -> ST Int = Char -> State -> (State, Int) instance Functor ST where -- fmap :: (a -> b) (ST a) -> (ST b) fmap g st = \s -> let (s', x) = st s in (s', g x) instance Monad ST where return x = \s -> (x, s) -- (>>=) :: (ST a) (a -> ST b) -> ST b st >>= f = \s -> let (s' , x) = st s in f x s' relabel trees with new fresh integer: tree :: Tree Char tree = Node (Leaf 'a') (Node (Leaf 'b') (Leaf 'c')) rlabel :: (Tree a) Int -> (Tree Int, Int) rlabel (Leaf _) n = (Leaf n, n+1) rlabel (Node l r) n = (Node l' r', n'') where (l', n') = rlabel l n (r', n'') = rlabel r n' fresh :: ST Int fresh = \n -> (n+1, n) mlabel :: Tree a -> ST (Tree Int) mlabel (Leaf _) = do n return (Leaf n) mlabel (Node l r) = do l' <- mlabel l r' <- mlabel r return (Node l' r') Feladat, ha a Standard Chartered-hez akarsz menni --------------------------------------------------------------- join :: m (m a) -> m a | Monad m join x = mma >>= \ma -> ma > join [[1,2],[3,4],[5,6]] [1,2,3,4,5,6] > join (Just (Just 1)) Just 1 > join (Just Nothing) Nothing > join Nothing Nothing join (*) Generic functions on monads --------------------------------------------------------------- mapM :: Monad m => (a -> m b) -> [a] -> m [b] mapM f [] = return [] mapM f (x:xs) = do y <- f x ys <- mapM f xs return (y:ys) conv :: Char -> Maybe Int conv c | isDigit c = Just (digitToInt c) | otherwise = Nothing > mapM conv "1234" Just [1,2,3,4] > mapM conv "123a" Nothing filterM :: Monad m => (a -> m Bool) -> [a] -> m [a] filterM p [] = return [] filterM p (x:xs) = do b <- p x ys <- filterM p xs return (if b then x:ys else ys) powerset: > filterM (\x -> [True,False]) [1,2,3] [[1,2,3],[1,2],[1,3],[1],[2,3],[2],[3],[]] replicateM :: Monad m => Int -> m a -> m [a] Monad torvenyek --------------------------------------------------------------- return x >>= f = f x mx >>= return = mx (mx >>= f) >>= g = mx >>= \x -> f x >>= g Viszony funktorokkal --------------------------------------------------------------- Mutasd meg, hogy minden monad funktor. Tovabbi monadok --------------------------------------------------------------- identitas e-> reader monad (e,) writer monad Funkcionalis programozas es algebra? --------------------------------------------------------------- a->b b^a (a,b) a*b Either a b a+b () 1