- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
天哪,我讨厌“代码味道”这个词,但我想不出更准确的词了。
我正在设计一种高级语言和编译器 Whitespace在业余时间学习编译器构建、语言设计和函数式编程(编译器是用 Haskell 编写的)。
在编译器的代码生成阶段,我必须在遍历语法树时维护“状态”数据。例如,在编译流程控制语句时,我需要为要跳转到的标签生成唯一名称(从传入、更新和返回的计数器生成的标签,并且绝不能再次使用计数器的旧值)。另一个例子是,当我在语法树中遇到内联字符串文字时,它们需要永久转换为堆变量(在空白中,字符串最好存储在堆上)。我目前正在将整个代码生成模块包装在状态 monad 中来处理这个问题。
有人告诉我,编写编译器是一个非常适合函数范式的问题,但我发现我的设计方式与用 C 语言设计它的方式大致相同(你真的可以用任何语言编写 C 语言)语言 - 甚至带有状态单子(monad)的 Haskell)。
我想学习如何在 Haskell 中思考(而不是在函数范式中),而不是使用 Haskell 语法的 C 语言。我真的应该尝试消除/最小化状态单子(monad)的使用,还是它是一个合法的功能“设计模式”?
最佳答案
我已经用 Haskell 编写了多个编译器,状态 monad 是许多编译器问题的合理解决方案。但你想让它保持抽象——不要让人明显地看出你正在使用 monad。
这是来自 Glasgow Haskell 编译器的示例(我不是编写的;我只是围绕一些边缘进行工作),我们在其中构建控制流图。以下是制作图表的基本方法:
empyGraph :: Graph
mkLabel :: Label -> Graph
mkAssignment :: Assignment -> Graph -- modify a register or memory
mkTransfer :: ControlTransfer -> Graph -- any control transfer
(<*>) :: Graph -> Graph -> Graph
但正如您所发现的,维护唯一标签的供应充其量是乏味的,因此我们还提供了这些功能:
withFreshLabel :: (Label -> Graph) -> Graph
mkIfThenElse :: (Label -> Label -> Graph) -- branch condition
-> Graph -- code in the 'then' branch
-> Graph -- code in the 'else' branch
-> Graph -- resulting if-then-else construct
整个Graph
事物是一个抽象类型,翻译者只是以纯函数的方式愉快地构造图,而不知道任何单子(monad)正在发生。然后,当最终构建图时,为了将其转换为我们可以生成代码的代数数据类型,我们为其提供唯一标签,运行状态 monad,并提取数据结构。
状态单子(monad)隐藏在下面;虽然它没有暴露给客户端,但是Graph
的定义是这样的:
type Graph = RealGraph -> [Label] -> (RealGraph, [Label])
或者更准确一点
type Graph = RealGraph -> State [Label] RealGraph
-- a Graph is a monadic function from a successor RealGraph to a new RealGraph
状态单子(monad)隐藏在抽象层后面,一点也不臭!
关于haskell - 使用 Haskell 状态 monad 有代码味道吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/607830/
我有一个单独的 Customer 模型的 View ,该模型在构造时获取一个客户和客户集合。客户模型的需求是有道理的——它是客户的 View 。收藏的要求……我不确定那是不是一种气味,希望得到反馈!
我试图在不同的风格中使用相同的 activity 名称,并为每种风格安装正确的名称。 build.gradle : android { .... buildscript {
我是一名优秀的程序员,十分优秀!