HOME Haskell �Τ��ٶ� download �񤭹���

8. Monad


����ʸ��Ǥ� Monad �ˤĤ��ƽҤ٤ޤ���Monad ���������ʤ������Τ�ʤ� �׻����Ȥ߹�碌���ˡ�ǡ�õ����IO����ʸ���� �ʤɤ˻Ȥ��ޤ���

Monad �ϼ¤Ϥ���ۤ��񤷤���ǰ�ǤϤ���ޤ��� "Haskell �� Monad ��Ȥäƻ���Ʃ�����򤪤������Ȥʤ� IO ��¸����Ƥ��롣" �Ȥ���������ʸ��䡢"Monad �����򤹤�Τ��񤷤����⤷��ʤ�" �ʤɤȤ������� �򵤤ˤ��ʤ��ǡ�Haskell 98 �ˤ�������򸫤��ʬ����䤹���Ȼפ��ޤ���

��� Haskeller �� Monad ���Ȥ����񤷤����Ȥ���ޤ����� ����� Monad ���񤷤��ΤǤϤʤ������Τ�äƤ��뤳�Ȥ��񤷤������Ǥ��� �ĤޤꡢMonad ��Ȥ����񤷤����Ȥ�����뤬��Monad ���Τ�Τ��񤷤��櫓�ǤϤʤ� �Ȥ������ȤǤ���

1. Monad �� class

Haskell 98 �Ǥ� Monad �Ȥ����Τ� class �ʤĤޤ����δؿ��Υ��åȡˤȤ����������Ƥ��ޤ��� ���ޤˡ�"List �� Monad" �Ȥ����褦�ʥե졼���򸫤����ޤ����� ���Τˤϡ�"List �� Monad �� instance �Ǥ��롣"��"List �ˤ� Monad ������" �ޤ��ϡ� "Monad �� instance �� List ([a]) �Ȥ��� data ���������Ƥ���" �Ȥ������Ȥˤʤ�ޤ��� ���äơ�class Monad ���������Ƥ������δؿ��� data ���ˤ�äư㤦ư��򤹤� ���Ȥˤʤ�ޤ���show �� (==) �Τ褦��ʬ����䤹�����δؿ����� data ���ˤ�äư㤦ư��򤷤Ƥ� ���ˤʤ�ޤ��󤬡�������ʤ� Monad �����δؿ��� data �����Ȥ�ư��㤦�Ⱥ��𤹤뤫�⤷��ޤ��� ���Τ褦�ʻ�������夤�ơ�Haskell 98 �򸫤Ƥߤ�Τ��ɤ��Ȼפ��ޤ���

����Ǥϡ�class Monad ������򸫤Ƥߤޤ��礦�����Τ褦�ˤʤäƤ��ޤ���

[code 1]

-- in predefined types and class
class  Monad m  where
    (>>=)   :: m a -> (a -> m b) -> m b
    (>>)    :: m a -> m b -> m b
    return  :: a -> m a
    fail    :: String -> m a

    m >> k  =  m >>= \_ -> k
    fail s  = error s
[code 1] ���� class Monad �ˤ� 4 �Ĥ����δؿ� (>>=), (>>), return, fail �� ���뤳�Ȥ�ʬ����ޤ����ޤ��� "class Monad m where" �Ȥ� "m a" ���Ȥ� "m b" �Ȥ��ä����Ҥ� ����Τǡ� ���������δؿ��� Maybe, List, IO �ʤɤβ���ʣ��Ū data ���˴ؤ����Τ��� �������ȡ�����ˡ�raturn �Ȥ� fail �Ȥ���ñ�줬�ߤ���Τǡ����Ԥ��뤫�⤷��ʤ� �׻��˴ؤ�äƤ���Ȥ������Ȥ�ʬ����ޤ���

����ˡ�

    (>>=)   :: m a -> (a -> m b) -> m b
���顢(>>=) �ϰ����Ȥ��ơ�
  1. ʣ�緿 data 'm a' �ȡ�
  2. a ����ʣ�緿 data 'm b' ����ؿ�
��Ȥꡢ ʣ�緿 data m b ���֤��ⳬ�ؿ��Ǥ��뤳�Ȥ��狼��ޤ���

�����ơ�(>>) �ϡ�

    m >> k  =  m >>= \_ -> k
���顢m ���ͤ�ΤƤơ�k ��ƤӽФ��ؿ��Ǥ��뤳�Ȥ�ʬ����ޤ��� (Lisp �� progn �˻��Ƥ��ޤ���)

�ʾ�Τ��Ȥ��顢Monad �Ȥ����Τϼ��Ԥ��뤫�⤷��ʤ��׻���Ĥʤ���碌�� ���δؿ����Ǥ��뤳�Ȥ�ʬ����ޤ���

2. Maybe �� Monad

����ޤǤ��ä����Ū�᤮��ʬ����ˤ����Τǡ� ��ñ�����󤲤������������Ȼפ��ޤ��� Monad �Τ����ǰ��ִ�ñ�ʤΤ� Maybe �� Monad �ǡ��ʲ��Τ褦���������Ƥ��ޤ���

[code 2]

-- in standard-prelude
instance  Monad Maybe  where
    (Just x) >>= k   =  k x
    Nothing  >>= k   =  Nothing
    return           =  Just
    fail s           =  Nothing
�Ĥޤꡢ�ʲ��Τ褦�ˤʤ�ޤ���
  1. Just x �򼡤η׻� k ���Ϥ��� k x �ˤʤ롣 �ʤĤޤꡢJust ��������äƼ��η׻����Ϥ�����
  2. Nothing �ϼ��η׻��عԤäƤ� Nothing �Ǥ��롣
  3. return �� Just �Ǥ��롣
  4. fail s �� Nothing �Ǥ��롣

��: ʸ������������Ѵ�

ʸ������������Ѵ����뤳�Ȥ�ͤ��ޤ��礦���ޤ��� ��ʸ�������ɤ߹���ؿ� s2i ��������ޤ��礦�� s2i �� ʸ���󤫤���Ƭ�Σ�ʸ�����ɤ߹���ǡ��������Ѥ���ؿ��Ǥ���[code 3] 10--13 ���ܡˡ� s2i ��������ʸ����� tuple ������˼�ꡢ[example 1] �Τ褦��ư��򤷤ޤ���

[example 1]

01:     EasyMonad> s2i (0,"12345")
02:     Just (1,"2345")
03:     EasyMonad> s2i (1, "2345")
04:     Just (12,"345")
[code 3]
01:     -- easy_monad.hs
02:     -- a small script for haskell8.html
03:     
04:     module EasyMonad where
05:     
06:     import Char
07:     
08:     --- Let's convert a String to Int if the String is [0-9]+
09:     -- s2i is a (reading one character) function
10:     s2i :: (Int, String) -> Maybe (Int, String)
11:     s2i (i, "") = Just (i, "")
12:     s2i (i, c:cs) | isDigit c = Just (i*10 + ord c - ord '0', cs)
13:                   | otherwise = Nothing
14:     
15:     -- same as s2i, written in Monadic term
16:     s2i' :: (Int, String) -> Maybe (Int, String)
17:     s2i' (i, "") = return (i, "")
18:     s2i' (i, c:cs) | isDigit c = return (i*10 + ord c - ord '0', cs)
19:                    | otherwise = fail "The char is not Digit"
20:     
21:     -- whole function to convert string to Maybe Int
22:     str2int :: String -> Maybe Int
23:     str2int "" = Nothing
24:     str2int str = iter (0, str)
25:      where iter (i, "") = Just i
26:            iter (i, cs) = let p = s2i (i, cs)
27:                           in if p == Nothing
28:                                  then Nothing
29:                                  else p >>= iter
���Υ����ɤ���Ͽ�� easy_monad.hs �����äƤ���Τǡ������ hugs �ʤɤ�����Ū�ʽ����Ϥ� load ����[example 2] �Τ褦�ˤ���ͷ��ǤߤƤ��������� ʸ�����ɤ߹��ޤ�Ƥ����ͻҤ�(>>=) �λȤ�����ʬ����Ȼפ��ޤ���

[example 2]

EasyMonad> s2i (0, "123")     -- read one
Just (1,"23")
EasyMonad> s2i (0, "123") >>= s2i             -- read two
Just (12,"3")
EasyMonad> s2i (0, "123") >>= s2i >>= s2i     -- read three
Just (123,"")
EasyMonad> s2i (0, "12a") >>= s2i >>= s2i     -- I cannot convert "12a" into an Int
Nothing
EasyMonad> s2i (0, "abc") >>= s2i >>= s2i     -- I cannot convert "abc" into an Int, either
Nothing
s2i' (code 1, 16--19 ���ܡ� �� s2i �� Monad �Ѹ�ǽ񤭴�������ΤǤ�������Ʊ�ͤ�ư��ޤ���

str2int (code 1, 22--29 ���ܡˤ� s2i ���Ѥ��� String �� Maybe Int ���Ѵ����� �ؿ��Ǥ���

EasyMonad> str2int "12345"
Just 12345
EasyMonad> str2int "12+345"
Nothing
�����㤫�� Monad ���ΤϤ���ʤ��񤷤��ʤ����Ȥ����򤫤ꤤ���������Ȼפ��ޤ���

3. Monad §

�׻��򥹥ࡼ���ˤĤʤ��뤿��ˡ�Monad �������������δؿ��ϣ��Ĥ� Monad §���������ʤ���Фʤ�ޤ��� ��¸�� Monad �����Ƥ��ξ����������Ƥ��ޤ��������ܤε�§�ϡ����˼����׻��η��§���ݾڤ����ΤǤ���
       c1 >>= c2 >>= c3
��     (c1 >>= c2) >>= c3
��     c1 >>= (c2 >>= c3)  (�� 1) 
�� 1: ��Τϳ�ǰŪ�˽񤤤���Ρ�Haskell �Υ����ɤȤ��ƽ񤯤� c1 >>= (\x -> c2 x >>= c3) ��

������ Monad ����Ȥ��� Monad §���������褦�ˤ��Ʋ�������

[Monad §]

return a >>= k = k a
m >>= return = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
��� Maybe �� Monad �� Monad §���������Ƥ��뤳�Ȥ��ǧ���Ƥߤޤ��礦��
-- Law 1
return x >>= k   ��   Just x  >>= k   ��    k x

-- Law 2
Just x >>= return    ��    return x      ��        Just x

-- Law 3
Just y >>= (\x -> k x >>= h)   
 ��       (\x -> k x >>= h) y                  
 ��        k y >>= h
 ��       (Just y >>= k) >>= h  

4. IO �� Monad

Haskell �Ǥϡ�IO �η�̤Ȥ����������ͤϡ�IO a �Ȥ��� ���������a �Ȥ϶��̤���ޤ�����������ȡ�IO �η�̤�ľ�ܤϡ��ؿ��ΰ����ˤ��뤳�Ȥ� ����ʤ��Τǡ����Τδؿ���ʬ�λ���Ʃ�������ݻ�����ޤ���

IO �η�̤�ؿ����Ϥ����� IO �� Monad ���������Ƥ��ޤ��� '...' ����ʬ�ϼ����˰�¸���ޤ���

instance Monad IO where
   (>>=)  = ...
   return = ...
   fail s = ioError (userError s)

5. do ��ˡ

do ��ˡ�� (>>=), (>>) ��Ȥä��̾�ε�ˡ�ι�ʸ����Ǥ��� do ��ˡ���Ѥ���ȼ�³���������ˤʤ�Τ� IO �ʤɤ򵭽Ҥ���Ȥ���ʬ����䤹���ʤ�ޤ���
�ʲ��� do ��ˡ���̾�ε�ˡ���������뵬§�򼨤��ޤ���
������ ������
do{foo} foo
do{foo; bazs} foo >> do{bazs}
do{let hoge; bazs} let hoge in do{bazs}
do{ p <- foo; bazs} let ok p = do{bazs} ; ok _ = fail "..." in foo >>= ok

�����ܤ�������§�� fail ���θ���Ƥ��뤿��츫�����ʬ����ˤ����ʤäƤ��ޤ����� ����Ū�ˤϰʲ��μ���Ʊ���Ǥ���
[������§ 4']

do{ p <- foo; bazs} �� foo >>= (\ p -&gt do{bazs})

�ʲ����̾�ε�ˡ�� do ��ˡ���Ѥ����������ץ������򼨤��ޤ���

01:     -- simple echo
02:     -- do notation
03:     my_echo :: IO()
04:     my_echo = do putStrLn "Enter something."
05:                  str <- getLine
06:                  putStrLn $ "You have entered: " ++ str
07:     
08:     -- conventional notation
09:     my_echo' :: IO()
10:     my_echo' = putStrLn "Enter something." >>
11:                getLine >>= (\str -> putStrLn $ "You have entered: " ++ str)

6. List �� Monad

List �� Monad �ϰʲ��Τ褦���������Ƥ��ޤ���
instance  Monad []  where
    m >>= k          = concat (map k m)
    return x         = [x]
    fail s           = []
(>>=) �� Maybe ���Ȥ����ְۤʤäƤ��ޤ��� List �ˤ����� (>>=) �ϡ��ꥹ�Ȥ��������Ƥ� k ����Ѥ����� ����� concat �ǤĤʤ���碌��Ȥ������ȤǤ��� �ޤ���return �ϥꥹ�Ȥ��뤳�ȡ� fail �϶��ꥹ�ȤǤ���

�ʲ��˥ꥹ�Ȥ����ǤΤ������������Ǥ���� c �ܤ���ؿ���

  1. �̾�ν��� (mul_odd1, 4--7 ���ܡ�
  2. Monad �Ѹ��Ȥä����� (mul_odd2, 10--13 ���ܡ�
  3. ����ɽ����Ȥä����� (mul_odd3, 16--17 ���ܡ�
�ǽ񤤤Ƥߤޤ����������δؿ�����Ӥ��顢����ɽ���� List �� Monad �ι�ʸ����Ǥ��뤳�Ȥ�ʬ����ޤ���
01:     --- Monad at List
02:     --- if odd then (*c) else fail
03:     --- list notation
04:     mul_odd1 :: Int -> [Int] -> [Int]
05:     mul_odd1 c xs = xs >>= (\x -> if odd x
06:                                       then [x*c]
07:                                       else [])
08:                                       
09:     --- monadic notation
10:     mul_odd2 :: Int -> [Int] -> [Int]
11:     mul_odd2 c xs = xs >>= (\x -> if odd x
12:                                       then return (x*c)
13:                                       else fail "I like odd.")
14:                                       
15:     ---  internal capsule
16:     mul_odd3 :: Int -> [Int] -> [Int]
17:     mul_odd3 c xs = [x*c | x <- xs, odd x]
EasyMonad> mul_odd2 10 [1,2,3,4,5]
[10,30,50]

7. mapM �� mapM_

map �� Monad ���Ȥ߹�碌��������ʤ��Ȥ�����ޤ��� mapM �� map �� (>>=) ��mapM_ �� map �� (>>) �� �Ȥ߹�碌����ΤǤ���
mapM_ �ϥꥹ�Ȥ����Ǥˣ������δؿ� f ����Ѥ������ͤ��֤��ޤ��� ������mapM �ϥꥹ�Ȥ����Ǥ� f ����Ѥ��������Ƥ����ǤˤĤ��� return ���֤����顢�֤äƤ����ͤΥꥹ�Ȥ��֤��ޤ��� ���������ĤǤ� fail ����������Τ� fail ���֤��ޤ��� ����ȡ���򼨤��ޤ���

[���]

sequence       :: Monad m => [m a] -> m [a] 
sequence       =  foldr mcons (return [])
                    where mcons p q = p >>= \x -> q >>= \y -> return (x:y)

sequence_      :: Monad m => [m a] -> m () 
sequence_      =  foldr (>>) (return ())

-- The xxxM functions take list arguments, but lift the function or
-- list element to a monad type

mapM             :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f as        =  sequence (map f as)

mapM_            :: Monad m => (a -> m b) -> [a] -> m ()
mapM_ f as       =  sequence_ (map f as)
[��]
foo :: [Int] ->IO()
foo = mapM_ print
{-
foo [1,2,3] �� sequence_ $ map print [1,2,3]
            �� sequence_ [(print 1), (print 2), (print 3)]
            �� print 1 >> print 2 >> print 3
-}

baz :: [Double] -> Maybe [Double]
baz xs = mapM  bar xs
 where bar x = if x > 0
                   then return (sqrt x)
                   else fail "I like positive."

{-
baz [1,4,9] �� sequence [Just 1.0, Just 2.0, Just 3.0]
            �� Just [1.0, 2.0, 3.0]

baz [1,-4,9] �� sequence [Just 1.0, Nothing, Just 3.0]
            �� Nothing
-}

8. ������

Monad �ˤĤ��Ƥ� All about Monad �����ܸ����� �˾ܤ����񤤤Ƥ���ޤ��� �ޤ��� haskell.org �� Web ��� Monad �β��⵭���ΰ���������ޤ���
HOME Haskell �Τ��ٶ� download �񤭹���