Haskell/SYB
外观
< Haskell
“抛弃你的样板代码” 方法,在 [1] 中“描述”,是一种允许你的数据结构被所谓的“泛型”函数遍历的方法:也就是说,函数抽象化了正在创建或修改的特定数据构造函数,同时允许为特定类型添加情况。
例如,如果你想序列化代码中的所有结构,但你只想编写一个在 Data.Data.Data 类(可以用 -XDeriveDataTypeable 推导)的任何实例上操作的序列化函数。
目标是将所有数据转换为以下格式
data Tag = Con String | Val String
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/