data Result t = Ok t | Err String deriving (Show, Eq) instance Functor Result where fmap f (Ok x) = Ok (f x) fmap _ (Err msg) = Err msg instance Applicative Result where pure = Ok Ok f <*> Ok x = Ok (f x) Ok f <*> Err msg = Err msg Err msg <*> _ = Err msg instance Monad Result where (Ok v) >>= k = k v (Err msg) >>= k = Err msg return v = Ok v fail msg = Err msg data Item = Item { id :: Int, name :: Maybe String } deriving (Show, Eq) getId :: Maybe Int -> Result Int getId Nothing = Err "No ID provided" getId (Just id) = Ok id getItem :: Int -> Result Item getItem id | id `rem` 2 == 0 = Ok ( Item id Nothing) | id `rem` 3 == 0 = Ok ( Item id (Just ("item-" ++ show id))) | otherwise = Err ("Item not found, ID = " ++ show id) getName :: Item -> Result String getName (Item id Nothing ) = Err ("Item has no name, ID = " ++ show id) getName (Item _ (Just name)) = Ok name doSomethingClever :: Int -> String -> String doSomethingClever id name = show id ++ " => " ++ name tryToDoSomethingClever :: Maybe Int -> Result String tryToDoSomethingClever idParam = do id <- getId idParam item <- getItem id name <- getName item return (doSomethingClever id name) demoInputs = [Nothing, Just 1, Just 2, Just 3] main = mapM_ (print . tryToDoSomethingClever) demoInputs