1

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

ユーザー ID を使用してプロファイルを照会できますが、Maybes に埋もれています。 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

これは機能しますが、最適ではありません - コードと 2 回のデータベース ヒットが繰り返されます。このコードをリファクタリングするにはどうすればよいですか?

私はこれがうまくいくと思った:

(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;
                                          .... };
           .... }

エラーは理解できますが、解決できません。

私を啓発します!

4

1 に答える 1

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)
于 2012-11-21T20:04:54.523 に答える