3

私は次の機能を持っています

type Assignment = [(Ref, Val)]

predi2 :: [(Val,Val)] -> Ref -> Ref -> (Maybe Assignment -> [Maybe Assignment])
predi2 f k1 k2 = \ma -> case ma of
    Nothing -> [Nothing]
    Just a -> case lookup k1 a of
        Nothing -> [Nothing]
        Just e1 -> case lookup k2 a of
            Nothing -> [Nothing]
            Just e2 -> if elem (e1, e2) f
                then [Just a]
                else []

Maybe のすべてのインスタンスを考えると、Maybe モナド内でもっと単純なものに単純化できると思いました。

predi2 :: [(Val,Val)] -> Ref -> Ref -> (Maybe Assignment -> [Maybe Assignment])
predi2 f k1 k2 = [\ma -> do
    a <- ma
    e1 <- lookup k1 a
    e2 <- lookup k2 a
    if elem (e1, e2) f then (return a) else ???]

しかし、私の問題は、何も返す必要がない最後の他のものです。

それが私の質問です: [fa] = [] のような方法で何も返さないことは可能ですか?

4

2 に答える 2

9

いいえ、ちがいます。

私はあなたの関数を次のように書きますpredi2

predi2 f k1 k2 ma = fromMaybe [Nothing] $ do
    a <- ma
    e1 <- lookup k1 a
    e2 <- lookup k2 a
    if elem (e1, e2) f then return [Just a] else return []

すなわち

  • を使用して、モナド計算を後処理しますfromMaybe
  • リストをモナド計算の外側ではなく内側に持つ
  • if ステートメントの False 分岐を成功としてカウントする (モナド計算の基準による)
于 2013-03-01T18:30:15.510 に答える
2

質問を正しく理解していれば、可能だと思います。

2 つの異なる種類の失敗を追跡しようとしていることに驚かされます。空のリストは、最終的なelemルックアップが失敗したことを示しています。Maybeは、(1) 元Maybe Assignmentが失敗したNothingか、(2)失敗したことを示しlookupます。これについては、より明確にすることができます。戻り値の型は次のようにする必要があります

data FailureType = Existence | SeenInF
Either FailureType Assignment

次に、 errorsモジュールを使用して、Maybeタイプ failures をEithersに変換します。

import Control.Error
predi2 :: [(Val, Val)] -> Ref -> Ref -> Maybe Assignment -> Either FailureType Assignment
predi2 f k1 k2 ma = do a  <- note Existence ma
                       e1 <- note Existence $ lookup k1 a
                       e2 <- note Existence $ lookup k2 a
                       note SeenInF $ guard $ (e1, e2) `elem` f
                       return a

Maybeこのソリューションは、2 つの失敗モナドとの間の変換を伴うため、少し奇妙ですEithernote、この目的には非常に便利な関数です。

于 2013-03-02T17:11:57.253 に答える