Skip to content

Instantly share code, notes, and snippets.

@jproyo
Last active May 19, 2022 16:04
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jproyo/7127418371a6d6254ff2208bf26c0315 to your computer and use it in GitHub Desktop.
Save jproyo/7127418371a6d6254ff2208bf26c0315 to your computer and use it in GitHub Desktop.
Tagless Final Encoding in Haskell Example
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
module Data where
type UserName = String
data DataResult = DataResult String
deriving (Eq, Show)
class Monad m => Cache m where
getFromCache :: String -> m (Maybe [DataResult])
storeCache :: [DataResult] -> m ()
class Monad m => DataSource m where
getFromSource :: String -> m [DataResult]
class Monad m => Logging m where
logMsg :: String -> m ()
newtype NotInCache a = NotInCache { unNoCache :: IO a }
deriving (Monad, Applicative, Functor)
instance Cache NotInCache where
getFromCache _ = NotInCache $ return Nothing
storeCache _ = NotInCache $ return ()
instance DataSource NotInCache where
getFromSource user = return $ [DataResult $ "source: " <> user]
instance Logging NotInCache where
logMsg = NotInCache . putStrLn
newtype InCache a = InCache { unInCache :: IO a }
deriving (Monad, Applicative, Functor)
instance Cache InCache where
getFromCache user = InCache $ return $ Just [DataResult $ "cache: " <> user]
storeCache _ = InCache $ return ()
instance DataSource InCache where
getFromSource _ = InCache $ return []
instance Logging InCache where
logMsg = InCache . putStrLn
requestData :: (Cache m, DataSource m, Logging m) => UserName -> m [DataResult]
requestData userName = do
cache <- getFromCache userName
result <- case cache of
Just dataResult -> return dataResult
Nothing -> getFromSource userName
storeCache result
logMsg $ "Result data for user: " <> userName <> " - data: " <> show result
return result
main :: IO ()
main = do
(unNoCache $ requestData "john") >>= (putStrLn . show)
(unInCache $ requestData "john") >>= (putStrLn . show)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment