在Snap中避免链式查找的案例表达式

Ato*_*ton 3 monads haskell haskell-snap-framework

我正在使用Snap框架,我常常遇到这样的情况:我根据从表单字段获得的参数进行数据库查找.

考虑例如以下两个功能

getParam :: (MonadSnap m) => ByteString -> m (Maybe ByteString)
doLookup :: (MonadIO (m b v), MonadSnaplet m, MonadState s (m b b), HasAcid s UrlDB) => ByteString -> m b v (EventResult QueryByURL)
Run Code Online (Sandbox Code Playgroud)

其中UrlDB是整数和URL之间的映射.第二功能的复杂类型特征是由于使用酸状态并最终导致Maybe Integer.

queryByURL :: Text -> Query UrlDB (Maybe Integer)
Run Code Online (Sandbox Code Playgroud)

到目前为止,我的处理程序看起来像

indexHandler :: Handler MyApp MyApp ()
indexHandler = do
    mUrl <- getParam "url"
    case mUrl of
        Nothing  -> render "index"
        Just url -> do
            mId <- doLookup $ url
            case mId of
                Nothing -> render "index"
                Just i  -> do
                               fancyStuffWith i
                               render "index"
Run Code Online (Sandbox Code Playgroud)

现在,让我烦恼的第一件事是案例表达的阶梯式.第二件事是三重外观render "index".基本上,每当两个Maybe值中的一个为Nothing时,我想返回一个默认视图.

最干净的方法是什么?

mig*_*yte 5

这就是MaybeT monad变换器的用途.你的代码可以像这样写.

indexHandler :: Handler MyApp MyApp ()
indexHandler = do
    runMaybeT $ do
        url <- MaybeT $ getParam "url"
        i <- MaybeT $ doLookup url
        fancyStuffWith i
    render "index"
Run Code Online (Sandbox Code Playgroud)

错误包拉在一起,这些东西,并增加了很多的方便功能与他们合作.除了MaybeT之外,EitherT monad变换器也可以执行类似的操作,但会跟踪错误消息,以便您可以跟踪计算失败的时间.