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

使用maybe进行列表渲染错误的模式匹配

  •  0
  • Bercovici Adrian  · 技术社区  · 8 年前

    我应该如何使用 Just 分解模式时的构造函数?
    E、 G:
    如果我的模式是: (x1,x2,x3,....xn) 我必须用 只是 ?

    我的问题: 我正在尝试“安全地”实现Init函数。
    我必须使用 只是 第二排的尾巴和头?

    safeInit::[a]->Maybe [a]
    safeInit (x:xs)=x: safeInit (Just xs) #Just x : safeInit Just xs ?
    safeInit [x,y]=Just [x]
    safeInit _ =Nothing
    
    3 回复  |  直到 8 年前
        1
  •  5
  •   willeM_ Van Onsem    8 年前

    这里有两个问题:

    • 您使用作为输入的 Maybe [a] ;和
    • 第一个模式包含(严格的)超集,然后是第二个,因此第二个模式将 从不

    对于第一个问题,罪魁祸首是:

    safeInit (x:xs) = x: safeInit (Just xs)
    

    在这里 safeInit ,需要一个列表(类型 [a] ),但您将列表包装在 Just 构造函数,因此将其传递为 可能[答] 值,以及 安全初始化 无法处理此问题。因此,我们可以将其改写为:

    safeInit (x:xs) = x : safeInit xs
    

    然而,这将 解决问题,现在我们称之为“缺点”( : )在上 a 可能[答] ,函数无法处理此问题。我们首先必须检查递归调用是否生成 安全初始化 ,然后在 x 并在 只是 ,我们可以使用 fmap :

    safeInit (x:xs) = fmap (x:) (safeInit xs)
    

    对于第二个问题,我们可以重新安排条款:

    safeInit :: [a] -> Maybe a
    safeInit [x, _] = Just [x]
    safeInit (x:xs) = fmap (x:) (safeInit xs)
    safeInit [] = Nothing
    

    尽管如此,这种方法仍然存在一些问题:它相当低效,因为我们将 只是 所有元素(最后一个除外)的元素,前提是未优化。此外,如果我们处理一个无限列表,我们将陷入一个无限循环。我们可以通过使用一个内部函数来改进它,该函数计算 init 鉴于我们确信 初始化 是有效的。例如:

    safeInit :: [a] -> Maybe a
    safeInit (x:xs) = Just (go x xs)
        where go _ [] = []
              go x (x2:xs) = x : go x2 xs
    safeInit [] = Nothing
    
        2
  •  4
  •   leftaroundabout    8 年前

    这取决于你想要什么语义。如果 init ,一旦找到任何元素,您就知道结果实际上是 Just 无论如何,也就是说, Just init_xs 。然后,您希望在当前 x 添加到包含的列表,而不更改 只是 .最简单的方法是使用 Maybe Functor 实例:

    safeInit (x:xs) = (x:) <$> safeInit xs
    

    然而,请注意,这仅在放入额外的基本情况下有效,并且该子句必须 之前 通用缺点一:

    safeInit :: [a] -> Maybe [a]
    safeInit [_] = Just []
    safeInit (x:xs) = (x:) <$> safeInit xs
    safeInit []  = Nothing
    

    另一种可能更容易理解的方法是对递归结果进行模式匹配:

    safeInit (x:xs) = case safeInit xs of
          Just init_xs -> Just $ x : init_xs
          Nothing -> Just []
    safeInit [] = Nothing
    
        3
  •  3
  •   sshine    8 年前

    扩展Elmex80s的建议,

    safeInit :: [a] -> Maybe [a]
    safeInit [] = Nothing
    safeInit xs = Just (init xs)
    
    推荐文章