
-- Maybe monad folyt.
--------------------------------------------------------------------------------

-- emlékezzünk: Functor és Monad metódusok definíciója Maybe-hez.

-- (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
-- Just a  >>= f = f a
-- Nothing >>= _ = Nothing

-- (<$>) :: (a -> b) -> Maybe a -> Maybe b
-- f <$> Just a  = Just (f a)
-- f <$> Nothing = Nothing

-- pure :: a -> Maybe b
-- pure a = Just a

-- return = pure


   . Alkalmazzuk a ( > >   ( < $ > ) függvényeket   !


    a    , hogy ha a bement tartalmaz " a"-t ,
-- akkor a kimenet is tartalmazzon.
f1 :: Maybe (Maybe a) -> Maybe a
f1 (Just (Just a)) = Just a
f1 _               = Nothing

f1' :: Maybe (Maybe a) -> Maybe a
f1' mma = mma >>= \ma -> ma
     --   mma >>= id

-- Just ma >>= id = ma
-- Nothing >>= _  = Nothing

f1'' :: Maybe (Maybe a) -> Maybe a
f1'' (Just ma) = ma
f1'' Nothing   = Nothing

  f1 '' : :   = > m ( m a ) - > m a
--  (standard függvény: join)


  Alkalmazzuk mindhárom input   ( a , b , c ) hármas
  elemeire . Ha bármelyik függvény Nothing - ot ad ,   legyen Nothing ,
-- egyébként Just.
f2 :: (a -> Maybe a') -> (b -> Maybe b') -> (c -> Maybe c')
   -> (a, b, c) -> Maybe (a', b', c')
f2 f g h (a, b, c) = case (f a, g b, h c) of
  (Just a', Just b', Just c') -> Just (a', b', c')
  _                           -> Nothing


-- f2' f g h (a, b, c) = case f a of
--   Nothing -> Nothing
--   Just a' -> case g b of
--     Nothing -> Nothing
--     Just b' -> case h c of
--       Nothing -> Nothing
--       Just c' -> Just (a', b', c')

f2' :: (a -> Maybe a') -> (b -> Maybe b') -> (c -> Maybe c')
   -> (a, b, c) -> Maybe (a', b', c')
f2' f g h (a, b, c) =
  f a >>= \a' ->
  g b >>= \b' ->
  h c >>= \c' ->
  pure (a', b', c')
  -- return (a', b', c')

  -- zárójelezve
  f a > > = ( \a ' - >
  g b > > = ( \b ' - >
  h c > > = ( \c ' - >
  -- pure (a', b', c'))))

  emlékeztető : return és pure tökugyanaz , ajánlásom :  a pure - t
--   pure előnyösebb:
--     - rövidebb
      - más nyelvekben a return mást jelent


  Legyen a kimenet Nothing ha bármelyik bemenet listaelem Nothing ,
  egyébként Just < input   > .
f3 :: [Maybe a] -> Maybe [a]
f3 []       = pure []
f3 (ma:mas) =
  ma     >>= \a ->
  f3 mas >>= \as ->
  pure (a:as)

   f3 : :   = > [ m a ] - > m [ a ]


-- mapMaybe :: (a -> Maybe b) -> [a] -> Maybe [b]
  f3 = mapMaybe i d    -- (    a definíciót megérteni )


  emlékeztető : alkalmazzuk a függvényt páronként a kapott listák
  elemeire ! Ha a listák hossza   ,    a hosszabb
  lista kilógó elemeit .    ( + ) [ 1 , 1 , 1 ] [ 1 , 1 ] = = [ 2 , 2 ]
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f (a:as) (b:bs) = f a b : zipWith' f as bs
zipWith' f _      _      = []
  zipWith BSc - s anyag


-- Alkalmazzuk páronként a kapott (a -> b -> Maybe c) függvényt
  a bemenő listák elemeire !     ,
  akkor a kimenet legyen Nothing , egyébként Just < lista   >
zipWithMaybe :: (a -> b -> Maybe c) -> [a] -> [b] -> Maybe [c]
zipWithMaybe f (a:as) (b:bs) =
  f a b >>= \c ->
  zipWithMaybe f as bs >>= \cs ->
  pure (c:cs)
zipWithMaybe f _ _ = pure []   -- Just []

-- standard függvény zipWithMaybe
     neve : zipWithM ,   Control .    importálható

  definíció    Maybe 

zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM f (a:as) (b:bs) =
  f a b >>= \c ->
  zipWithM f as bs >>= \cs ->
  pure (c:cs)
zipWithM f _ _ = pure []

  példa :  ( \x y - > Just ( x + y ) ) [ 0 .. 10 ] [ 0 .. 10 ] = = Just [ 0,2,4,6,8,10,12,14,16,18,20 ]
         zipWithM ( \x y - > if x = = 0 then Nothing else Just y ) [ 0 .. 10 ] [ 0 .. 10 ]
         zipWithM ( \x y - > if x = = 0 then Nothing else Just y ) [ 1 .. 10 ] [ 0 .. 10 ] = = Just [ 0,1,2,3,4,5,6,7,8,9 ]

  példa :  ( \x y - > print ( x + y ) ) [ 0 .. 10 ] [ 0 .. 10 ]
--           (kinyomtatja a számok összegeit páronként)




   a következő típust , aminek   egyszerű kifejezésfák :
data Exp = IntLit Int | BoolLit Bool | Add Exp Exp | Not Exp | Eq Exp Exp
  deriving (Show)

-- pl.
  0 + 10
e2 = Eq (IntLit 0) e1           -- 0 == (a + 10)
e3 = Not e2                     -- not (0 == (0 + 10))

  Írjunk egy függvényt ,     kiértékel Either     !
  A    ,   összeadás , Eq egyenlőségvizsgálat ,
  és Not    . Minden olyan esetben , ha a kifejezés típushibás ,
  legyen   Nothing .

   :
-- eval (Eq (IntLit 0) (BoolLit True)) == Nothing
  eval ( IntLit 10 ) = = Just ( Left 10 )
  eval ( Add ( IntLit 10 ) ( IntLit 20 ) ) = = Just ( Left 30 )
  eval ( Not ( IntLit 10 ) ) = = Nothing

 Maybe monad folyt.
------------------------------------------------------------------------------
 emlékezzünk: Functor és Monad metódusok definíciója Maybe-hez.
 (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
 Just a  >>= f = f a
 Nothing >>= _ = Nothing
 (<$>) :: (a -> b) -> Maybe a -> Maybe b
 f <$> Just a  = Just (f a)
 f <$> Nothing = Nothing
 pure :: a -> Maybe b
 pure a = Just a
 return = pure
 akkor a kimenet is tartalmazzon.
   mma >>= id
 Just ma >>= id = ma
 Nothing >>= _  = Nothing
  (standard függvény: join)
 egyébként Just.
 f2' f g h (a, b, c) = case f a of
   Nothing -> Nothing
   Just a' -> case g b of
     Nothing -> Nothing
     Just b' -> case h c of
       Nothing -> Nothing
       Just c' -> Just (a', b', c')
 return (a', b', c')
 zárójelezve
 pure (a', b', c'))))
   pure előnyösebb:
     - rövidebb
 mapMaybe :: (a -> Maybe b) -> [a] -> Maybe [b]
 (    a definíciót megérteni )
 Alkalmazzuk páronként a kapott (a -> b -> Maybe c) függvényt
 Just []
 standard függvény zipWithMaybe
           (kinyomtatja a számok összegeit páronként)
 pl.
 0 == (a + 10)
 not (0 == (0 + 10))
 eval (Eq (IntLit 0) (BoolLit True)) == Nothing








   . Alkalmazzuk a ( > >   ( < $ > ) függvényeket   !


    a    , hogy ha a bement tartalmaz " a"-t ,
f1 :: Maybe (Maybe a) -> Maybe a
f1 (Just (Just a)) = Just a
f1 _               = Nothing

f1' :: Maybe (Maybe a) -> Maybe a
f1' mma = mma >>= \ma -> ma


f1'' :: Maybe (Maybe a) -> Maybe a
f1'' (Just ma) = ma
f1'' Nothing   = Nothing

  f1 '' : :   = > m ( m a ) - > m a


  Alkalmazzuk mindhárom input   ( a , b , c ) hármas
  elemeire . Ha bármelyik függvény Nothing - ot ad ,   legyen Nothing ,
f2 :: (a -> Maybe a') -> (b -> Maybe b') -> (c -> Maybe c')
   -> (a, b, c) -> Maybe (a', b', c')
f2 f g h (a, b, c) = case (f a, g b, h c) of
  (Just a', Just b', Just c') -> Just (a', b', c')
  _                           -> Nothing



f2' :: (a -> Maybe a') -> (b -> Maybe b') -> (c -> Maybe c')
   -> (a, b, c) -> Maybe (a', b', c')
f2' f g h (a, b, c) =
  f a >>= \a' ->
  g b >>= \b' ->
  h c >>= \c' ->
  pure (a', b', c')

  f a > > = ( \a ' - >
  g b > > = ( \b ' - >
  h c > > = ( \c ' - >

  emlékeztető : return és pure tökugyanaz , ajánlásom :  a pure - t
      - más nyelvekben a return mást jelent


  Legyen a kimenet Nothing ha bármelyik bemenet listaelem Nothing ,
  egyébként Just < input   > .
f3 :: [Maybe a] -> Maybe [a]
f3 []       = pure []
f3 (ma:mas) =
  ma     >>= \a ->
  f3 mas >>= \as ->
  pure (a:as)

   f3 : :   = > [ m a ] - > m [ a ]




  emlékeztető : alkalmazzuk a függvényt páronként a kapott listák
  elemeire ! Ha a listák hossza   ,    a hosszabb
  lista kilógó elemeit .    ( + ) [ 1 , 1 , 1 ] [ 1 , 1 ] = = [ 2 , 2 ]
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f (a:as) (b:bs) = f a b : zipWith' f as bs
zipWith' f _      _      = []
  zipWith BSc - s anyag


  a bemenő listák elemeire !     ,
  akkor a kimenet legyen Nothing , egyébként Just < lista   >
zipWithMaybe :: (a -> b -> Maybe c) -> [a] -> [b] -> Maybe [c]
zipWithMaybe f (a:as) (b:bs) =
  f a b >>= \c ->
  zipWithMaybe f as bs >>= \cs ->
  pure (c:cs)

     neve : zipWithM ,   Control .    importálható

  definíció    Maybe 

zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM f (a:as) (b:bs) =
  f a b >>= \c ->
  zipWithM f as bs >>= \cs ->
  pure (c:cs)
zipWithM f _ _ = pure []

  példa :  ( \x y - > Just ( x + y ) ) [ 0 .. 10 ] [ 0 .. 10 ] = = Just [ 0,2,4,6,8,10,12,14,16,18,20 ]
         zipWithM ( \x y - > if x = = 0 then Nothing else Just y ) [ 0 .. 10 ] [ 0 .. 10 ]
         zipWithM ( \x y - > if x = = 0 then Nothing else Just y ) [ 1 .. 10 ] [ 0 .. 10 ] = = Just [ 0,1,2,3,4,5,6,7,8,9 ]

  példa :  ( \x y - > print ( x + y ) ) [ 0 .. 10 ] [ 0 .. 10 ]




   a következő típust , aminek   egyszerű kifejezésfák :
data Exp = IntLit Int | BoolLit Bool | Add Exp Exp | Not Exp | Eq Exp Exp
  deriving (Show)

  0 + 10

  Írjunk egy függvényt ,     kiértékel Either     !
  A    ,   összeadás , Eq egyenlőségvizsgálat ,
  és Not    . Minden olyan esetben , ha a kifejezés típushibás ,
  legyen   Nothing .

   :
  eval ( IntLit 10 ) = = Just ( Left 10 )
  eval ( Add ( IntLit 10 ) ( IntLit 20 ) ) = = Just ( Left 30 )
  eval ( Not ( IntLit 10 ) ) = = Nothing
