【问题标题】:What is "Scrap Your Boilerplate"?什么是“废弃你的样板”?
【发布时间】:2015-03-30 09:58:21
【问题描述】:

我看到人们在 Haskell 中谈论 Scrap Your Boilerplate泛型编程。这些术语是什么意思?我什么时候想使用 Scrap Your Boilerplate,如何使用?

【问题讨论】:

  • Google 在这方面有大量文档......
  • @JustinPihony 我问这个问题是因为 Stack Overflow 的目标之一是回答 所有 编程问题,even those that can be Googled。这个问题,据我所知,以前从未在 SO 上提出过,我相信它会产生一些高质量的答案。
  • Scrap your boilerplate - A Practical Design Pattern for Generic Programming 论文的第 2 部分包含一个很好的激励示例。
  • FWIW,我经常想知道这个问题的答案是什么。 SYBP 的文档庞大而复杂,似乎没有描述它实际上试图解决...的问题

标签: haskell functional-programming generic-programming scrap-your-boilerplate


【解决方案1】:

通常在对复杂数据类型进行转换时,我们只需要影响结构的一小部分——换句话说,我们只针对特定的可简化表达式、redexes。

典型的例子是对一种整数表达式的双重否定消除:

data Exp = Plus Exp Exp | Mult Exp Exp | Negate Exp | Pure Int

doubleNegSimpl :: Exp -> Exp
doubleNegSimpl (Negate (Negate e)) = e
...

即使在描述这个例子时,我也不想写出整个... 部分。它完全是机械的——只不过是在整个Exp 中继续递归的引擎。

这个“引擎”是我们打算废弃的样板。


为了实现这一点,Scrap Your Boilerplate 提出了一种机制,通过它我们可以在数据类型上构建“通用遍历”。这些遍历完全正确地运行,而对所讨论的特定数据类型一无所知。为此,非常粗略地说,我们有一个通用注释树的概念。它们比 ADT 大,因此所有 ADT 都可以投影到带注释的树的类型中:

section :: Generic a => a -> AnnotatedTree

并且“有效的”带注释的树可以投射回某个品牌的 ADT

retract :: Generic a => AnnotatedTree -> Maybe a

值得注意的是,我引入了Generic 类型类来指示定义了sectionretract 的类型。

使用所有数据类型的这种通用的、带注释的树表示,我们可以一劳永逸地定义遍历。特别是,我们提供了一个接口(策略性地使用sectionretract),以便最终用户永远不会接触到AnnotatedTree 类型。相反,它看起来有点像:

everywhere' :: Generic a => (a -> a) -> (AnnotatedTree -> AnnotatedTree)

这样,结合最终和初始 sectionretracts 以及我们的注释树始终“有效”的不变量,我们有

everywhere :: Generic a => (a -> a) -> (a -> a)
everywhere f a0 = fromJust . retract . everywhere' f . section

everywhere f a 是做什么的?它尝试在 ADT a 中应用函数 f "everywhere"。换句话说,我们现在将双重否定化简写成如下

doubleNegSimpl :: Exp -> Exp
doubleNegSimpl (Negate (Negate e)) = e
doubleNegSimpl e                   = e

换句话说,只要 redex (Negate (Negate _)) 匹配失败,它就会充当 id。如果我们对此应用everywhere

simplify :: Exp -> Exp
simplify = everywhere doubleNegSimpl

然后双重否定将通过通用遍历“无处不在”被消除。 ... 样板已消失。

【讨论】:

  • everywhere 如何判断一个模式是否成功匹配?通常,非穷举模式会抛出一个必须在IO 中捕获的异常。
  • 它没有。 doubleNegSimpl 是当 redex 不匹配时的身份,所以 everywhere 实际上只是在 所有地方 应用它,并且在大多数地方它只是一个无操作。当然,everywhere 小心翼翼地高效地做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-05
  • 2021-12-03
  • 2020-04-19
相关资源
最近更新 更多