2

ここに少しサンプルコードがあります

foo :: a -> Identity (Maybe a)
foo a = do
  maybeStuff <- getStuffSometimes a
  return $ case maybeStuff of                  -- this "case" stuff is the kind
    Just stuff -> Just $ getStuffAlways stuff  -- of code I'd expect the Maybe
    Nothing -> Nothing                         -- monad to help with

getStuffSometimes :: a -> Identity (Maybe a)
getStuffSometimes a = return $ Just a

getStuffAlways :: a -> Identity a
getStuffAlways = return

-- ERROR (on the return statement of the do block)
-- Expected type: Identity (Maybe a)
--   Actual type: Identity (Maybe (Identity a))

私がやろうとしていることは少し不明確かもしれないので、ここにより詳細な説明があります:

  • 興味深いものはすべて、計算コンテキスト/コンテナー (この場合はIdentity、デモンストレーションのために ) にラップされています。私の実際のコードでは、もちろん別のモナドがあります。

  • foogetStuffSometimes型の何かを取り、コンテキストでラップされたaを返すことになっています。つまり、(計算が成功したか、または(計算が失敗しました) を返します。Maybe aIdentity (Just a)Identity Nothing

  • getStuffAlwaysは決して失敗しない計算であり、常に を返しますIdentity a

  • 私がしたいfoo:

    1. 失敗可能な計算を実行する
    2. 失敗可能な計算が失敗した場合、失敗します (Nothing を使用)
    3. 失敗可能な計算が成功した場合は、それを getStuffAlways でバインドし、戻ります Just (result of getStuffAlways to the result of #1)

これは Monad Transformers の使用例ですか? 私の場合、実際のモナドは少し複雑で、IO の上に私のライブラリによって与えられた複数のトランスフォーマーのスタックであり、この状況でそれを機能させる方法が完全にはわかりません (別の質問で尋ねます変圧器を使わなければならないということになります)


ファローアップ:

実生活では、次のようなものがあります。

foo :: a -> Identity (a, Maybe a)
foo a = do
  firstPart <- getStuffAlways a

  maybeStuff <- getStuffSometimes a
  secondPart <- case maybeStuff of
    Just stuff -> Just $ getStuffAlways stuff
    Nothing -> Nothing

  return (firstPart, secondPart)

この場合、スタックを構築する最良の方法は何でしょうか?

4

1 に答える 1

5

はい、これはモナド変換子の使用例です。タイプの計算が与えられた場合:

computation :: (Monad m) => m (Maybe a)

...同じ名前のコンストラクターをMaybeT使用してラップできます。MaybeT

MaybeT :: (Monad m) => m (Maybe a) -> MaybeT m a

MaybeT computation :: (Monad m) => MaybeT m a

次に、次のように書くことができます。

foo :: MaybeT Identity a
foo = do
   stuff <- MaybeT getStuffSometimes
   lift $ getStuffAlways stuff

...そしてMaybeT、すべてのNothingチェックを処理し、それらを他のモナドに確実に通すようにします。

完了したら、 を使用runMaybeTして結果をアンラップし、次を返す基本モナドのアクションを返しますMaybe

runMaybeT :: (Monad m) => MaybeT m a -> m (Maybe a)

例えば:

runMaybeT foo :: Identity (Maybe a)

編集:フォローアップの質問に答えるには、次のようにします。

foo a = do
    firstPart <- getStuffAlways
    secondPart <- runMaybeT $ do
        stuff <- MaybeT getStuffSometimes a
        lift $ getStuffAlways stuff
    return (firstPart, secondPart)
于 2013-08-02T21:46:12.890 に答える