跳转到内容

Haskell/SYB

来自维基教科书,开放世界中的开放书籍

“抛弃你的样板代码” 方法,在 [1] 中“描述”,是一种允许你的数据结构被所谓的“泛型”函数遍历的方法:也就是说,函数抽象化了正在创建或修改的特定数据构造函数,同时允许为特定类型添加情况。


例如,如果你想序列化代码中的所有结构,但你只想编写一个在 Data.Data.Data 类(可以用 -XDeriveDataTypeable 推导)的任何实例上操作的序列化函数。

序列化示例

[编辑 | 编辑源代码]

目标是将所有数据转换为以下格式

data Tag = Con String | Val String

比较 Haskell AST

[编辑 | 编辑源代码]

haskell-src-exts 包 将 Haskell 解析为一个相当复杂的语法树。假设我们想检查两个几乎相同但名称不同的源文件是否等价。

首先

import System.Environment
import Language.Haskell.Exts

main = do
   -- parse the filenames given by the first two command line arguments,
   -- proper error handling is left as an exercise
   [ParseOk moduleA, ParseOk moduleB] <- mapM parseFile . take 2 =<< getArgs

   putStrLn $ if moduleA == moduleB
        then "Your modules are equal"
        else "Your modules differ"

从一些测试中可以明显看出,具有不同名称的相同文件不会等于 (==)。但是,为了纠正这一点,而不诉诸大量样板代码,我们可以使用泛型编程

待办事项

[编辑 | 编辑源代码]

描述使用 Data.Generics.Twins.gzip*? 编写一个函数来查找差异之处?

或者使用它来编写一个 geq 的变体,忽略无关紧要的特定情况(SrcLoc 元素)(即 syb 不允许泛型扩展……将其与其他库对比?)。

或者只是解释这个技巧(效果很好),它在 (==) 之前运行,或者 geq:

everyWhere (mkT $ \ _ -> SrcLoc "" 0 0) :: Data a => a -> a

或者我们能将其发展为编写比 sim_mira(用于 hs 代码)更好的东西,这里找到:http://dickgrune.com/Programs/similarity_tester/

华夏公益教科书