- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在用 Haskell 开发一门新语言,我遇到了句法树 T
脱糖的问题。
我有一组函数f1, f2,... fn
,它们从“糖”中简化树T
。它们被分成不同的递归函数,因此代码更具可读性(每个函数都有一些特定的任务,并且比将它们实现为一个递归更容易理解它们在做什么)。
用于脱糖的组合函数如下所示
f :: T -> T
f = f1 . f2 . f3 . ... . fn
我读过(并且我认为)Haskell 中的最佳实践是,您以某种方式表示数据,它们不会得到错误/未定义/不可能的值。问题是,每个函数 f1
,...,fn
基本上都通过某些构造函数减少了类型 T。 (例如,应用于 T 的 f1 删除了一些糖,由一些构造函数表示,这些构造函数不能出现在任何后续函数 f2
,...,fn
中)。
因此,为了保持最佳实践,我必须以某种方式定义类型 T1, T2,..., Tn
,其中
f1 :: T -> T1
f2 :: T1 -> T2
...
fn :: Tn-1 -> Tn
请问我该怎么做? 我曾考虑使用 Haskell 模板,但在我看来这有点矫枉过正。 是否有一些多态性方法?能否在不牺牲代码可读性的情况下克服此实现?
我说的是最佳实践,这可能会被社区认为是基于意见的,所以我进一步解释一下。
所有函数 f1, f2,...,fn
都依赖于它们的前任。但是,如果 T
类型从 f1, f2,...,fn
传入和传出,编译器
发出许多关于模式匹配的警告(如果它们没有被错误“This shouldn't be possible”
正确处理)
我没有得到关于代码正确性的很好的编译检查。编译器不知道,我是否不做某事,这是不可能的。 (例如,使用已被删除的语法糖)
为简单起见,我们假设 Haskell 模板 Language.Haskell.TH.Exp
。如果我想对语言处理使用相同的方法,我可能想将 f1
定义为函数,它替换所有 ArithSeqE
([ 1 ,2 .. 10 ]
) 为 AppE
s (f x
) 生成算术序列。
现在,我想(以某种方式)从 Language.Haskell.TH.Exp
- T1
中定义一个新类型,它禁止使用构造函数 ArithSeqE
,因此编译器知道它不能在任何进一步的 T2,T3,...Tn
中,因此 f2,f3,...,fn
不必对其进行模式匹配,也无法使用它。
最佳答案
我只能解决您的部分问题。我希望即使是部分解决方案也能激发更好的想法。
我的想法是参数化你的总和类型,每个构造函数有一个类型参数,你可以消除。这个想法是,虽然构造函数将保留,但您可以对它们进行参数化,以便它们无人居住。这样一来,虽然编译器仍然会提醒您匹配不可能的构造函数,但您的脱糖步骤之一实际上不可能将这样的构造函数留在原地。
假设你有这种类型:
data Expr = Value Int
| Pair Value Value
| Values [Expr]
您可能有一个脱糖步骤,将每个 Pair 替换为一个双元素 Values 构造函数。首先,我们需要用单字段构造函数替换双字段构造函数:
data PairContents = PairContents Value Value
data Expr = Value Int
| Pair PairContents
| Values [Expr]
然后,我们添加一个类型参数,允许我们允许或禁止 PairContents:
newtype No x = No Void
data PairContents = PairContents Value Value
data Expr pairf = Value Int
| Pair (pairf PairContents)
| Values [Expr]
现在,删除所有 Pair 构造函数的重构步骤可以具有类型
desugarPairs :: Expr Identity -> Expr No
Expr No
不可能包含任何Pair
构造函数,因为它的Pair
字段的类型是No PairContents
,它是 Void
,因此无法居住。
正如我所说,我的方法存在几个问题。这意味着如果你有 10 个重构步骤,每个重构步骤都需要 10 个类型参数;你仍然需要在下一步中对 Pair
进行模式匹配,即使你知道这是不可能的。我希望有人能有更好的建议。但至少这完成了一些事情:可以依靠您的重构步骤去除了它们声称去除的所有糖分。
关于parsing - 如何正确地脱糖语法树? - 减少数据结构定义/构造函数禁用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71270854/
在此处回答的另一个问题中,我发现了以下 JavaScript代码: function _dom_trackActiveElement(evt) { if (evt && evt.target)
if (A == 0) OR (B == 0) 怎么说? 最佳答案 只是为了讽刺: if (A === 0 || B === 0) 关于语法,我们在Stack Overflow上找到一个类似的问题:
var ret = [] ,xresult = document.evaluate(exp, rootEl, null, X
我一直在寻找一些类似于下例的 JavaScript。有人可以解释一下吗,因为我以前从未见过这样编写的 JavaScript。 “SomethingHere”和冒号代表什么?我习惯于看到函数 myFun
这是我的程序: delimiter // drop procedure if exists migContactToActor; create procedure migContactToActor(
我遇到了一个问题。我一直在使用 gcc 编译/汇编我的 C 代码一段时间,并且习惯了阅读 Intel 汇编语法。我在生成程序集文件时使用了 -masm=intel 标志。 但是最近因为公司迁移,拿到了
自上而下和自下而上语法有什么区别?举个例子就太好了。 最佳答案 首先,语法本身不是自上而下或自下而上的,解析器是(尽管有些语法可以被其中一个解析,但不能被另一个解析)。 从实践的角度来看,主要区别在于
我知道这是草率的代码,但它是: display dialog ("Start Screensaver. Please type: matrix, coffee, waffles, star, wate
这个问题已经有答案了: Giving name to a loop (6 个回答) 已关闭 8 年前。 我见过这个字符在 C# 中使用,就像 Java 中的扩展一样,但最近我在代码中发现了这个 loo
我正在尝试编写一个函数来检查字符串是否为回文,但我认为在使用字符串指针时存在一些错误。这段代码有什么问题? #include #include #define MAX 1000 int IsPalin
所以在this question我询问了一些 Javascript 是如何被压缩的。问题已得到解答,但以下片段让我非常困惑,以至于我不得不问另一个问题。在这里: for (Y = 0; $ = 'zx
假设我有一个接受这些参数的函数。 int create(Ptr * p,void * (*insert)(void *, void *)) { //return something later } 结
这个问题已经有答案了: Bitwise '&' operator (6 个回答) 已关闭 5 年前。 我在代码中找到了这个,但我从未遇到过像 & 这样的事情,仅 && if ((code & 1) =
我在处理继承类及其中的构造函数和方法的语法时遇到了问题。 我想实现一个类日期和一个子类 date_ISO,它们将按特定顺序设置给定的日、月、年,并通过一种方法将其写入字符串。我觉得我的基类日期工作正常
我正在尝试通过存储过程填充表,如下所示: SET @resultsCount = (SELECT COUNT(*) FROM tableA); SET @i = 0; WHILE @i THEN
谁能解释一下下面代码中的“<<”? mysql test<
刚刚开始学习 MySQL,这是一个菜鸟问题,也是我在 StackOverflow 上的第一个问题。 假设我有 12 个订单状态,我想从其中的 5 个中选择总计。我会使用: SELECT SUM(tot
我的编程背景是在学校学过一点Java。由于某些原因,JavaScript 语法往往让我感到困惑。下面的 JavaScript 代码是一种我不知道如何构成的语法模式: foo.ready = funct
我正在阅读 javascript 源代码,并且我以前没有编写过 javascript。我对它的一些语法感到困惑。 $(function () { window.onload=function
我什至不知道如何命名我想要的东西。那么让我举个例子来解释一下。 虽然火狐使用textContent,但其他浏览器支持innerText属性。顺便说一句,如果我使用了错误的术语,请纠正我。无论如何,到目
我是一名优秀的程序员,十分优秀!