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 monad 中将其简化为更简单的东西:

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 ???]

但我的问题是最后的 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 []

IE

  • 后处理一元计算,使用fromMaybe
  • 将列表放在 monadic 计算内部,而不是在其外部
  • 让 if 语句的 False 分支算成功(根据单子计算的标准)
于 2013-03-01T18:30:15.510 回答
2

如果我正确理解了这个问题,我认为这是可能的。

令我印象深刻的是,您正在尝试跟踪两种不同类型的故障,空列表表示最终elem查找失败。Maybe表示 (1) 原件失败Maybe AssignmentNothing(2)lookup失败。我们可以更明确地说明这一点。返回类型应该类似于

data FailureType = Existence | SeenInF
Either FailureType Assignment

然后我们将使用errors模块将Maybe类型失败转换为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并且Either, 但是note对于这个目的来说是一个非常有用的函数。

于 2013-03-02T17:11:57.253 回答