- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
现在,我有一些代码基本上是这样工作的:
data Expression
= Literal Bool
| Variable String
| Not Expression
| Or Expression Expression
| And Expression Expression
deriving Eq
simplify :: Expression -> Expression
simplify (Literal b) = Literal b
simplify (Variable s) = Variable s
simplify (Not e) = case simplify e of
(Literal b) -> Literal (not b)
e' -> Not e'
simplify (And a b) = case (simplify a, simplify b) of
(Literal False, _) -> Literal False
(_, Literal False) -> Literal False
(a', b') -> And a' b'
simplify (Or a b) = case (simplify a, simplify b) of
(Literal True, _) -> Literal True
(_, Literal True) -> Literal True
(a', b') -> Or a' b'
还有更多这样的模式,涉及简化 bool 表达式的所有方式。然而,当我添加更多的运算符和规则时,它会极大地增长并且感觉......笨重。特别是因为一些规则需要添加两次以考虑交换性。
我怎样才能很好地重构很多很多模式,其中一些(我想说大多数)甚至是对称的(例如 And 和 Or 模式)?
现在,添加一条规则来将 And (Variable "x") (Not (Variable "x")))
简化为 Literal False
需要我添加两个嵌套规则,这几乎是最佳的。
最佳答案
基本上,问题在于您必须一遍又一遍地写出每个子句中子表达式的simplify
。最好先完成所有子表达式,然后再考虑涉及顶级运算符的定律。一种简单的方法是添加 simplify
的辅助版本,它不会向下递归:
simplify :: Expression -> Expression
simplify (Literal b) = Literal b
simplify (Variable s) = Variable s
simplify (Not e) = simplify' . Not $ simplify e
simplify (And a b) = simplify' $ And (simplify a) (simplify b)
simplify (Or a b) = simplify' $ Or (simplify a) (simplify b)
simplify' :: Expression -> Expression
simplify' (Not (Literal b)) = Literal $ not b
simplify' (And (Literal False) _) = Literal False
...
由于 bool 值中的运算量很少,这可能是最明智的方法。然而,随着操作的增多,simplify
中的重复可能仍然值得避免。为此,您可以将一元和二元操作合并到一个公共(public)构造函数中:
data Expression
= Literal Bool
| Variable String
| BoolPrefix BoolPrefix Expression
| BoolInfix BoolInfix Expression Expression
deriving Eq
data BoolPrefix = Negation
data BoolInfix = AndOp | OrOp
然后你就得到了
simplify (Literal b) = Literal b
simplify (Variable s) = Variable s
simplify (BoolPrefix bpf e) = simplify' . BoolPrefix bpf $ simplify e
simplify (BoolInfix bifx a b) = simplify' $ BoolInfix bifx (simplify a) (simplify b)
显然这会让simplify'
变得更加尴尬,所以也许不是一个好主意。然而,您可以通过定义专门的 pattern synonyms 来解决这种语法开销。 :
{-# LANGUAGE PatternSynonyms #-}
pattern Not :: Expression -> Expression
pattern Not x = BoolPrefix Negation x
infixr 3 :∧
pattern (:∧) :: Expression -> Expression -> Expression
pattern a:∧b = BoolInfix AndOp a b
infixr 2 :∨
pattern (:∨) :: Expression -> Expression -> Expression
pattern a:∨b = BoolInfix OrOp a b
就此而言,也许也是
pattern F, T :: Expression
pattern F = Literal False
pattern T = Literal True
有了这个,你就可以写了
simplify' :: Expression -> Expression
simplify' (Not (Literal b)) = Literal $ not b
simplify' (F :∧ _) = F
simplify' (_ :∧ F) = F
simplify' (T :∨ _) = T
simplify' (a :∧ Not b) | a==b = T
...
我应该添加一个警告:when I tried something similar to those pattern synonyms, not for booleans but affine mappings, it made the compiler extremely slow 。 (此外,GHC-7.10 尚不支持多态模式同义词;到目前为止,这已经发生了很大变化。)
<小时/>另请注意,所有这些通常不会产生最简单的形式 -为此,您需要找到simplify
的不动点。
关于haskell - Haskell 中广泛模式匹配的更清晰替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45486842/
你好,我是 Cone。 首先,我们思考一个问题。 为什么会有操作系统? 在我们教科书上会提到分时系统、批处理系统等等现代操作系统前的中间产物,也会讲到管理硬件的功能,但似乎没有讲到为什么有
假设我只想清除顶部的所有条目,清除 Map 的 Map 的最合适方法是什么 -关卡 map ? Map> nestedMap; 方法A:仅清除顶层 map 。 nestedMap.clear();
我时不时遇到一个问题,我不确定解决方案是什么。 我有一个 2 列布局(左边是 strit,然后是主要区域)。在主要区域,我有时会有一个次要的 2 栏布局(例如 - 对于新闻部分,那里有一个图标,然后是
我有以下代码: Created Created .clearfix:after{ clear: both; bdy: "."; display
有没有办法CLS单行输出?我不相信 CLS 有任何开关,所以也许更好的问题是: 有什么办法吗 保留所有以前的输出以供重复使用? 或 捕获当前显示的输出(就像通过标记和复制一样)? 我只是想通过实时反馈
我有一个流式布局。当布局足够宽时,一些 div(.one 和 .two)可以全部水平排列在一条线上。 当布局最终被挤压时,右侧 float 的 div (.two) 最终会出现在多行上。有没有一种方法
我面临着一个我真的不知道从哪里开始解决的问题,所以我希望这个问题不要太宽泛。 我正在制作并在屏幕上应用它,我将有一个包含一些信息的矩形(假设它是一个 )并且我需要用另一个矩形覆盖那个矩形,所以当用户
我的 UITableView 跨越 iPhone View 的大小,并有一个 tableHeaderView 保存附加内容。想要标题清晰,表格的其余部分白色,我将表格的背景颜色设置为清晰,并在 Vie
我一直在使用 ImageMagick,但它产生的结果非常模糊。 convert -density 300 ../images/favicons/procensus.svg -background tr
我有手动数据的工作项目,但我想在我的项目中添加 json 解析。我认为我需要帮助。 (必须是实时解析,如果可能的话,新的item添加时会自动释放) 我的 TableView 代码 - (void)sc
我正在制作一个响应式网站。我有 3 个 div (.block),我需要将它们水平放置在一起。 当屏幕足够宽时,这很容易实现。但是,当我使浏览器更窄时,第三个 div (3) 换行到下一行,但我想要的
如何在 Swift 3 中使这个 UITableView 和它的单元格清晰。 我已经完成了前面的线程,但我仍然得到一个白色背景。 正如您从我的代码中看到的,我已经尝试了提到的各种方法: overrid
当我使用 为了显示图标,它在谷歌浏览器中看起来非常清晰锐利。然而,当我在 Firefox 或 Internet Explorer 中打开 svg 时,图标看起来很模糊。 这些浏览器似乎将图标呈现为半像
我是一名优秀的程序员,十分优秀!