Haskell后续功能有什么作用?

时间:2017-12-19 16:35:43

标签: haskell

我对haskell很新,但幸运的是我需要实现一些功能。 我对以下功能有疑问

next :: Eq a => [a] -> a ->  a
next l@(x:_) e = case dropWhile (/= e) l of
                   (_:y:_) -> y
                   _ -> x
  • l@做什么?
  • dropWhile (/= e) l of代表什么,尤其是/=运算符
  • of在这种情况下的含义是什么?
  • (_:y:_)做什么?我知道(x:xs)会让你抓住头部或尾部,但y变量中的内容是什么?
  • 箭头会做什么? _ -> x

1 个答案:

答案 0 :(得分:13)

所有好问题!

  
      
  • l@做什么?
  •   

这称为 as-pattern 。它给出了整个模式的名称。 l@(x:_)是一种匹配具有至少一个元素的列表的模式。它将列表的头部命名为x,丢弃列表的尾部,并命名整个列表(即表达式x:_l的值。

  
      
  • dropWhile (/= e) l of代表什么,尤其是/=运算符
  •   

/=是Haskell如何拼写“不相等”。它与例如Java中的!=相同。语法(/= e),其中中缀运算符在括号中给出一个参数,称为 section 。它代表(\x -> x /= e)。因此,dropWhile (/= e) l会删除l中的元素,只要它们不等于e

  
      
  • of在这种情况下的含义是什么?
  •   

它只是case表达式语法的一部分。它将scrutinee与树枝分开:

case foo of
    bar -> ...
    baz -> ...
    ...
  
      
  • (_:y:_)做什么?我知道(x:xs)会让你抓住头部或尾部,但y变量中的内容是什么?
  •   

这只是一个更复杂的模式。在这个例子中,它匹配列表至少包含两个元素,并命名第二个元素y

x:xs将头部与尾巴分开; x:(y:ys)将前两个元素与其余元素分开。由于(:)是右关联的,因此您可以删除括号(x:y:ys),而_只是表示“我对此不感兴趣”。

  
      
  • 箭头会做什么? _ -> x
  •   

同样,它只是case表达式语法的一部分。它将模式与返回值分开。在这种情况下,模式是一个包罗万象的通配符模式,返回值为x

总结一下:这个函数应该在e中查找l并返回以下元素。也就是说,这并不是一个特别伟大的实现。我侦察了两个特别的问题。

  1. 如果输入列表为空,它将以异常(并使程序崩溃!)失败,因为在[]的声明中没有next个案的子句。 next部分功能。
  2. 如果dropWhile (/= e) l未返回包含至少两个元素的列表(以便_:y:_模式不匹配),则它将返回x,即列表。 (如果列表中缺少e或者它是最后一个元素,可能会发生这种情况。)这似乎是一件非常奇怪的事情。
  3. 我可能会通过考虑甚至可能没有next l元素的可能性来解决这个问题。 e可能是l的最后一个元素,或者根本不在l。这是此函数含义的基本部分,而不仅仅是实现中的错误,因此我们应该在类型中考虑它。

    next :: Eq a => [a] -> a -> Maybe a
    

    通过向next提供Maybe a的返回类型,我表示它可能不会返回任何内容。

    next l e = case dropWhile (/= e) l of
                    (_:x:_) -> Just x
                    _ -> Nothing
    

    所以这个实现说:如果dropWhile (/= e) l返回至少两个元素的列表,则返回第二个元素。 (我正在使用Just :: a -> Maybe a将值包装到Maybe中。)否则返回Nothing

    不要过于担心这一点,但是对于它的价值,我们可以使用Haskell的一个更高级的功能使这个功能略微缩短。 ViewPatterns语言扩展旨在简化此类功能,仅对次要值执行case分析。

    {-# LANGUAGE ViewPatterns #-}
    next :: Eq a => a -> [a] -> Maybe a  -- I've flipped the arguments
    next e (dropWhile (/= e) -> _:x:_) = Just x
    next _ _ = Nothing