Mar*_*cin 0 haskell syntactic-sugar
我想知道如果没有任何语法糖,以下函数会是什么样子:
tails1 :: [a] -> [[a]]
tails1 [] = [[]]
tails1 xs@(x:xs') = xs:tails1 xs'
Run Code Online (Sandbox Code Playgroud)
我最关心的是 @ 运算符的用法,我已经尝试了以下操作,但这显然不是正确的方法
tails1 ((:) x ((:) xs' [])) = xs:tails1 xs'
Run Code Online (Sandbox Code Playgroud)
在其他答案中,我们看到了两个提案:
tailsA (x:xs') = (x:xs'):tailsA xs
tailsB xs = xs:tailsB (tail xs)
Run Code Online (Sandbox Code Playgroud)
前者具有正确的指称语义,但具有错误的操作语义。原来tails只有一个调用(:);tailsA因此,人们可能会担心,与 的原始定义相比,足够愚蠢的编译器在运行时会分配额外的 cons 单元tails。后者也有正确的表示,并且只有一次调用,但插入了一个原始函数中没有出现的(:)全新函数;tail这种转变似乎需要一些程序员的洞察力才能执行。下面,我将展示如何以一种不需要程序员洞察力(因此可以由编译器执行)并且不存在额外分配风险的方式将原始定义转换为没有 at 模式的定义。
tailsC xs = case xs of
x:xs' -> xs:tailsC xs'
Run Code Online (Sandbox Code Playgroud)
这里特别有趣的是:原始方程的右侧逐字显示为 case 语句的右侧。(根本不包含tailsA或不tailsB包含原始方程的右侧作为子项。)此特殊情况转换建议的 at 模式的一般翻译并不完全正确(因为xs匹配任何值,而xs@(x:xs')仅匹配非空列表);将 Haskell 风格的模式转换为 GHC-Core 风格的 case 语句(仅检查单个变量,并且其模式全部包含一个构造函数)的完整处理超出了 StackOverflow 答案的范围。已经有几篇研究论文讨论了如何正确、有效地做到这一点并生成快速的代码;另请参阅相关问题类型检查类 ML 模式匹配的算法?并且基本上所有的结果都在Google Scholar搜索中进行编译模式匹配。
但基本思想是匹配name@pattern时精确匹配pattern(将所有相同的名称pattern绑定到所有相同的值),但另外绑定name到完整值。