当前位置:  开发笔记 > 开发工具 > 正文

模式匹配比Haskell中的case表达更优选的现实例子?

如何解决《模式匹配比Haskell中的case表达更优选的现实例子?》经验,为你挑选了1个好方法。

所以我一直忙于真实世界Haskell书,我做了lastButOne练习.我想出了两个解决方案,一个是模式匹配

lastButOne :: [a] -> a
lastButOne ([]) = error "Empty List"
lastButOne (x:[]) = error "Only one element"
lastButOne (x:[x2]) = x
lastButOne (x:xs) = lastButOne xs

一个使用案例表达

lastButOneCase :: [a] -> a
lastButOneCase x =
  case x of
    [] ->  error "Empty List"
    (x:[]) ->  error "Only One Element"
    (x:[x2]) ->  x
    (x:xs) ->  lastButOneCase xs

我想知道的是模式匹配何时优先于case表达式,反之亦然.这个例子对我来说不够好,因为看起来虽然两个函数都按预期工作,但它并没有让我选择一个实现而不是另一个.所以选择"看起来"优先乍一看?

那么有没有通过源代码获得好的案例,无论是在haskell自己的源代码还是github或其他地方,哪里可以看到哪种方法是首选的?



1> Daniel Wagne..:

首先是一个简短的术语转移:我会称之为"模式匹配".我不确定是否有一个很好的术语来区分模式匹配 - 通过案例和模式匹配 - 通过多重定义.

两者之间的技术区别确实很轻.您可以通过要求GHC使用-ddump-simpl标志转储为两个函数生成的核心来自行验证.我在几个不同的优化级别尝试了这一点,并且在所有情况下,核心的唯一差异是命名.(顺便说一下,如果有人知道Core的一个好的"语义差异"程序 - 它至少知道alpha等价 - 我很有兴趣听到它!)

不过,有一些小问题需要注意.您可能想知道以下内容是否也是等效的:

{-# LANGUAGE LambdaCase #-}
lastButOne = \case
  [] ->  error "Empty List"
  (x:[]) ->  error "Only One Element"
  (x:[x2]) ->  x
  (x:xs) ->  lastButOneCase xs

在这种情况下,答案是肯定的.但请考虑这个看起来相似的一个:

-- ambiguous type error
sort = \case
  [] -> []
  x:xs -> insert x (sort xs)

突然间,这是一个类型类多态CAF,所以在旧的GHC上,这将触发单态限制并导致错误,而具有显式参数的表面相同的版本不会:

-- this is fine!
sort [] = []
sort (x:xs) = insert x (sort xs)

另一个微小的区别(我忘记了 - 感谢Thomas DuBuisson提醒我)是在处理where子句.由于where子句附加到绑定站点,因此它们不能跨多个方程共享,但可以跨多个案例共享.例如:

-- error; the where clause attaches to the second equation, so
-- empty is not in scope in the first equation
null [] = empty
null (x:xs) = nonempty
  where empty = True
        nonempty = False

-- ok; the where clause attaches to the equation, so both empty
-- and nonempty are in scope for the entire case expression
null x = case x of
  [] -> empty
  x:xs -> nonempty
  where
  empty = True
  nonempty = False

您可能认为这意味着您可以使用不能用case表达式执行的方程式执行某些操作,即在两个方程中对同一名称具有不同的含义,如下所示:

null [] = answer where answer = True
null (x:xs) = answer where answer = False

但是,由于case表达式的模式是绑定站点,因此也可以在case表达式中进行模拟:

null x = case x of
  [] -> answer where answer = True
  x:xs -> answer where answer = False

当然,where条款是附加到case模式还是等式取决于缩进.


"我不确定是否有一个很好的术语来区分模式匹配 - 通过案例和模式匹配 - 通过多重定义." [Hudak,Hughes,Peyton Jones和Wadler关于Haskell历史的论文](http://haskell.cs.yale.edu/wp-content/uploads/2011/02/history.pdf)称这种"宣言风格"(对于多个方程式)与"表达式"(对于`case`表达式).
推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有