【问题标题】:Simplify code by distributing []通过分发 [] 来简化代码
【发布时间】:2013-03-01 18:11:32
【问题描述】:

我有以下功能

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,我不需要返回任何内容。

这是我的问题:是否有可能以 [f a] = [] 的方式返回任何内容?

【问题讨论】:

    标签: list haskell monads


    【解决方案1】:

    不,不是。

    我会把你的 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 分支算作成功(根据单子计算的标准)

    【讨论】:

      【解决方案2】:

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

      令我震惊的是,您正在尝试跟踪两种不同类型的故障,空列表表示最终的 elem 查找失败。 Maybe 表示 (1) 原始 Maybe Assignment 是 Nothing 或 (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 是一个非常有用的函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-08
        • 1970-01-01
        • 2022-12-23
        • 1970-01-01
        • 2021-09-28
        • 1970-01-01
        • 2019-11-27
        • 1970-01-01
        相关资源
        最近更新 更多