import Text.Read (readMaybe) data Rating = Bad | Good | Great deriving Show data ServiceStatus = Ok | Down deriving Show type BookID = Int type HandlerAction a = IO a type ReqHandler a = BookID -> HandlerAction a data BookInfoAPIImpl = BookInfoAPIImpl { root :: HandlerAction ServiceStatus, title :: ReqHandler String, year :: ReqHandler Int, rating :: ReqHandler Rating } impl = BookInfoAPIImpl { root = pure Ok, title = \_ -> pure "Haskell in Depth", year = \_ -> pure 2020, rating = \_ -> pure Great } impl2 = BookInfoAPIImpl { root = pure Down, title = \_ -> notImplemented, year = \_ -> notImplemented, rating = \_ -> notImplemented } where notImplemented = ioError (userError "not implemented") type Request = [String] encode :: Show a => HandlerAction a -> IO String encode m = show <$> m route :: BookInfoAPIImpl -> Request -> Maybe (IO String) route impl [] = pure $ encode $ root impl route impl [op, bid'] = do bid <- readMaybe bid' case op of "title" -> pure $ title impl bid "year" -> pure $ encode $ year impl bid "rating" -> pure $ encode $ rating impl bid _ -> Nothing route _ _ = Nothing get :: BookInfoAPIImpl -> Request -> IO String get impl xs = case route impl xs of Just m -> m Nothing -> pure "Wrong request" check impl = do b <- get impl [] answer <- get impl ["year", "7548"] putStrLn (if b == "Ok" && answer == "2020" then "OK" else "Wrong answer!") main = check impl