使用约束构建通用函数

函数

1
2
3
4
5
6
7
8
9
10
handleDBException :: SomeException -> HandlerFor site (Either DatabaseException a)
handleDBException e =
let eMsg = T.pack $ show e
in
if "Duplicate" `T.isInfixOf` eMsg
then return $ Left DuplicateEntryException
else return $ Left $ GeneralDatabaseException eMsg

tryDbAction :: YesodDB site a -> HandlerFor site (Either DatabaseException a)
tryDbAction dbAction = ( Right <$> dbAction) `catch` handleDBException

上述函数并没有使用到HandlerFor这个类型相关的函数,完全可以用Monad约束代替。

1
2
3
4
5
6
7
8
9
10
handleDBException :: Monad m => SomeException -> m (Either DatabaseException a)
handleDBException e =
let eMsg = T.pack $ show e
in
if "Duplicate" `T.isInfixOf` eMsg
then return $ Left DuplicateEntryException
else return $ Left $ GeneralDatabaseException eMsg

tryDbAction :: (Functor m, Monad m, MonadUnliftIO m) => m a -> m (Either DatabaseException a)
tryDbAction dbAction = ( Right <$> dbAction) `catch` handleDBException

newtype

在构建newtype的时候也是一样,例如构建一个ReaderT

1
2
newtype ServeFor site param a = ServeFor (ReaderT (ServiceContext param) (HandlerFor site) a)
deriving (Functor, Applicative, Monad, MonadIO, MonadResource, MonadLogger)

也可以修改如下

1
newtype Monad m => ServeFor param m a = ServeFor (ReaderT (ServiceContext param) m a)