``````findOrder :: String -> Maybe Order
findOrder number = -- 一些程式碼

findCustomer :: Order -> Maybe Customer
findCustomer order = -- 一些程式碼

findCustomer customer = -- 一些程式碼
``````

``````address =
case findOrder "X1234" of
Nothing -> Nothing
Just order -> case findCustomer order of
Nothing -> Nothing
``````

`fmap` 的型態是 `(a -> b) -> f a -> f b`，因為 `findOrder``findCustomer``findAddress` 等函式的型態，都是 `a -> Maybe b`，我們沒辦法直接將 `findOrder``findCustomer``findAddress` 直接當作 `fmap` 的第一個引數，就算你勉強寫出了以下的程式，Callback hell 只會令情況更糟：

``````address = case fmap (\order ->
fmap (\customer -> findAddress customer) (findCustomer order))
(findOrder "X1234") of Nothing -> Nothing
``````

``````case f something1 of
Nothing -> Nothing
Just something2 -> case f something2 of -- 重複的結構
``````

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

``````address = findOrder "X1234" `may` findCustomer `may` findAddress
``````

``````class Monad m where
return :: a -> m a

(>>=) :: m a -> (a -> m b) -> m b

(>>) :: m a -> m b -> m b
x >> y = x >>= \_ -> y

fail :: String -> m a
fail msg = error msg
``````

``````instance Monad Maybe where
return x = Just x
Nothing >>= _ = Nothing
(Just something) >>= f = f something
``````

``````address = findOrder "X1234" >>= findCustomer >>= findAddress
``````

``````instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
fail _ = []
``````

``````main = do
name <- getLine
putStrLn  ("哈囉, " ++ name)
``````

`getLine` 的傳回型態是 `IO String`，你取得其中的 `String`，然後執行 `putStrLn`，得到一個 `IO ()`，也就是說你做了一個從 `String -> IO ()` 的動作，將一開始 `IO String` 對應至 `IO ()`，那麼，`IO` 可以是個 `Monad` 嗎？是的！上面的程式也可以這麼寫：

``````main =
(getLine >>= (\name -> putStrLn ("Hello, " ++ name)))
``````

• `return a >>= k == k a`
• `m >>= return == m`
• `m >>= (\x -> k x >>= h) == (m >>= k) >>= h`