代码之家  ›  专栏  ›  技术社区  ›  Bercovici Adrian

如何基于一元模式匹配进行过滤?[副本]

  •  1
  • Bercovici Adrian  · 技术社区  · 6 年前

    我有以下问题:

    给定类型 data T = T (Maybe Int) ,如何筛选获取非- Nothing

    输入

    a = [T (Just 3), T Nothing, T (Just 4)]
    

    期望输出

    b = [T (Just 3), T (Just 4)]
    

    b = filter (\x-> x@(Just t)) a 
    

    …认为我可以根据模式匹配进行筛选,但我得到了错误:

    Pattern syntax in expression context: x@(Just t)
        Did you mean to enable TypeApplications?
    

    I want to Just

    3 回复  |  直到 6 年前
        1
  •  4
  •   willeM_ Van Onsem    6 年前

    我认为在这里我们可以更好地使用列表理解的模式匹配语义:

    result = [ e | e@(T (Just _)) <- a]
    

    e 在里面 a ,如果模式匹配 T (Just _) 如果成功,我们将在结果列表中生成它。

    如果你愿意 封装在 T (Just x) ,我们就可以执行模式匹配,并生成包装的元素:

    result = [ e | T (Just e) <- a]

    T Nothing s被忽略,只有 T (Just e) e 我们最终会被列入名单。

        2
  •  3
  •   Ben    6 年前

    如果你想得到 Int T [T] -> [Int] ),那么 mapMaybe Data.Maybe 已经做了你想做的事。所有你需要的是一个类型的展开函数 T -> Maybe Int

    import Data.Maybe ( mapMaybe )
    
    data T = T (Maybe Int)
      deriving (Eq, Show)
    
    unT :: T -> Maybe Int
    unT (T x) = x
    
    filterTs = mapMaybe unT
    

    然后:

    λ a = [T (Just 3), T Nothing, T (Just 4)]
    a :: [T]
    
    λ filterTs a
    [3,4]
    it :: [Int]
    

    [T] ->[内景] 比让它返回 T型 Nothing 值;原因是即使您 a [T (Just 3), T (Just 4)] 仍然 Just 内景 价值观,即使你知道 1 ,因为 仍硬编码为包含 没有什么 .

    一般来说,如果要筛选(或默认设置等)以保证没有case,那么应该考虑转换为不再有case的类型。它通常使结果数据更容易处理(不需要模式匹配或 fmap 例如,它可以进入冗余层,并帮助避免bug。

    catMaybes :: [Maybe a] -> [a] ,这就是“过滤掉 没有映射“,但是既然你要映射来展开 建造师 地图也许 更合适。


    1 而这个“我知道永远不会 没有什么 在这里,所以我不必处理它“的情况是一个非常丰富的错误来源,容易打破时,某些东西的变化,隐藏在未来不变。因此,实际上编写代码来利用 没有什么 “不可能”在那里;你应该在那里 仍然 两个案子都处理!

        3
  •  2
  •   chepner    6 年前

    模式匹配只适用于 论点 为了功能,而不是身体。你需要匹配的模式是 T ,具有像 maybe 将包装值转换为布尔值。

    Prelude> a = [T (Just 3), T Nothing, T (Just 4)]
    Prelude> filter (\(T x) -> maybe False (const True) x) a
    [T (Just 3),T (Just 4)]
    

    maybe False (const True) 已定义为 Data.Maybe.isJust .

    Prelude> import Data.Maybe
    Prelude> filter (\(T x) -> isJust x) a
    [T (Just 3),T (Just 4)]
    

    如果有某种类型的函数,可以简化谓词 T -> Maybe Int 作曲 isJust . 例如:

    Prelude> data T = T { getT :: Maybe Int } deriving Show
    Prelude> a = [T (Just 3), T Nothing, T (Just 4)]
    Prelude> filter (isJust . getT) a
    [T {getT = Just 3},T {getT = Just 4}]
    
    推荐文章