使用Yesod,我想在每个页面的导航栏中显示用户的个人资料名称,并希望将ProfileId
链接到用户的个人资料页面。 config/models
包含:
User
ident Text
password Text Maybe
UniqueUser ident
Profile
username Text
user UserId
UniqueProfile user
UniqueUsername username
来自Foundation.hs
的片段:
defaultLayout widget = do
master <- getYesod
mmsg <- getMessage
maid <- maybeAuthId
使用user-id,我可以查询个人资料,但它已在Maybe
中被隐藏。
This Stack Overflow question提供了一个很好的提示如何处理所有这些Maybe
...但是,由于我对Haskell的一点经验,我仍然在努力解决它。
我想出了:
mpid <- runMaybeT $ do
ouid <- MaybeT maybeAuthId
(Entity pid _) <- MaybeT . runDB . getBy $ UniqueProfile ouid
return pid
mprofilename <- runMaybeT $ do
ouid <- MaybeT maybeAuthId
(Entity _ p) <- MaybeT . runDB . getBy $ UniqueProfile ouid
return $ profileUsername p
这可行,但不是最佳的 - 重复代码和双重数据库命中。我该如何重构这段代码?
我认为这样可行:
(mpid, mprofilename) <- runMaybeT $ do
ouid <- MaybeT maybeAuthId
(Entity pid p) <- MaybeT . runDB . getBy $ UniqueProfile ouid
return (pid, profileUsername p)
但是,唉,不禁:
Foundation.hs:91:9:
Couldn't match expected type `Maybe (t0, Text)'
with actual type `(t1, t2)'
In the pattern: (mpid, mprofilename)
In a stmt of a 'do' block:
(mpid, mprofilename) <- runMaybeT
$ do { ouid <- MaybeT maybeAuthId;
(Entity pid p) <- MaybeT . runDB . getBy $ UniqueProfile ouid;
return (pid, profileUsername p) }
In the expression:
do { master <- getYesod;
mmsg <- getMessage;
maid <- maybeAuthId;
(mpid, mprofilename) <- runMaybeT
$ do { ouid <- MaybeT maybeAuthId;
(Entity pid p) <- MaybeT . runDB . getBy
$ UniqueProfile ouid;
.... };
.... }
我理解错误,但我没有解决。
启发我!
答案 0 :(得分:3)
您尝试将结果绑定为(Maybe a, Maybe b)
,但它实际上是Maybe (a, b)
。
你可以轻松转换它:
unpairMaybe :: Maybe (a, b) -> (Maybe a, Maybe b)
unpairMaybe (Just (x, y)) = (Just x, Just y)
unpairMaybe Nothing = (Nothing, Nothing)
然后这应该有效:
(mpid, mprofilename) <- liftM unpairMaybe $ runMaybeT $ do
ouid <- MaybeT maybeAuthId
(Entity pid p) <- MaybeT . runDB . getBy $ UniqueProfile ouid
return (pid, profileUsername p)