6

1. ユーザーがログインしていること、2. ユーザーが特定のオブジェクトにアクセスできることを確認する認可スキームを設定しようとしています。このためにmaybeAuthId、まず を呼び出してから、現在のオブジェクトを取得し、アクセス許可を一覧表示する別のテーブルに「結合」します。多分ケースには 2 つのレベルがあり、空リストのケースには 1 つのレベルがあります。私は MaybeT を使用することを考えましたが、疲れすぎて機能しないか、「実際にはモナドトランスフォーマーではない」-handler-transformers は MaybeT では使用できません。深い多分を処理する良い方法はありますか?

編集:

ちょっとわかりにくかったようです。私は次のようなものを持っていることを意味しました:

case foo of
   Nothing -> something
   Just foo' -> do
      bar <- somethingelse
      case bar of
         Nothing -> ...
         Just bar' -> ...
4

3 に答える 3

6

MaybeTYesodに完全に使用できます。次のようにしてください:

runMaybeT $ do
  uid <- MaybeT maybeAuthID
  car <- MaybeT . runDB . getBy $ UniqueCarOwner uid
  location <- MaybeT . liftIO . ciaLocateLicensePlate . licensePlate $ car
  country <- MaybeT . findCountry $ location
  return (car, country)

あなたが言ったように、ほとんどの関数は Yesod の一般的なエラー処理用に最適化されていません。ただし、 の形のものがある場合は、 を使用して裏返しにして にするMonad m => m (Maybe a)ことができます。MaybeTMonad m => Maybe (m a)

于 2012-08-26T17:59:39.937 に答える
2

私が理解していることから、レイヤーは次のようになります。

Maybe [Maybe r]

join...そして、2 つの を一緒にしたいのですMaybeが、リストが邪魔です。これはまさに問題sequence解決です:

sequence :: (Monad m) => [m r] -> m [r]

モナドに特化sequenceすると、次のようになることに注意してください。Maybe

sequence :: [Maybe r] -> Maybe [r]

この特定のケースでは、リストに少なくとも 1 つある場合、sequenceは a を返しますが、それらがすべてs である場合は、それらすべてを 1 つの に結合します。NothingNothingJustJust

残っているのはsequence、outer をマップすることだけMaybeです。

fmap sequence :: Maybe [Maybe r] -> Maybe (Maybe [r])

これは、結合に必要なフォームとまったく同じです。

join . fmap sequence :: Maybe [Maybe r] -> Maybe [r]

したがって、直感的に、上記の関数が行うことは、すべての内側Maybeの がJustであり、外側のMaybeが である場合、結果全体をリストを含むJust1 つに融合することです。Justただし、いずれかMaybe(内側または外側のいずれか) が であるNothing場合、最終結果はNothingです。

盲目的な型追跡を何度も行ったにもかかわらず、最終的には直感的に正しいことを行う関数になったことに注意してください。これが圏論に基づく抽象化の力です。

于 2012-08-26T19:13:12.753 に答える
1

「深い多分を処理する」とはどういう意味かは明確ではありませんが、モナディックjoin(from Control.Monad) を使用して、一度に 1 レベルのネストを削除できます。

ghci> :m +Control.Monad
ghci> join (Just (Just 3))
Just 3
ghci> join (Just Nothing)
Nothing
ghci> join Nothing
Nothing

ただし、MaybeT を使用することは、おそらく問題により適しています。あなたが何をしようとしているのかを明確にすれば、MaybeT でそれを策定するのを手伝うことができます。

于 2012-08-26T15:11:30.257 に答える