{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
module Try.Monads.FunctionalDependencies where
import Data.Functor ((<&>))
-- Fundeps exercise - https://www.fpcomplete.com/haskell/tutorial/fundeps/#exercises
newtype PersonReader a = PersonReader {runPersonReader :: Person -> a}
deriving (Functor, Applicative, Monad)
class Monad m => MonadReader env m | m -> env where
ask :: m env
data Person = Person
{ nameP :: String
, ageP :: Int
}
deriving (Show)
askAge :: MonadReader Person m => m Int
askAge = ask <&> ageP
askName :: MonadReader Person m => m String
askName = ask <&> nameP
greeting :: forall m. (Monad m, MonadReader Person m) => m String
greeting = do
name <- askName
age <- askAge
pure $ name ++ " is " ++ show age ++ " years old"
instance MonadReader Person PersonReader where
ask :: PersonReader Person
ask = PersonReader id
greetingId :: String
greetingId = runPersonReader (greeting @PersonReader) Person{nameP = "ah", ageP = 3}
-- >>>greetingId
-- "ah is 3 years old"