我想使用函数名称的集合作为Data.Map键,并从该函数中自动获得每个函数的键。如有必要,我愿意考虑“不安全”的行动。
我的具体编程问题是:我一直在开发一个用于文本转换的简单解析器库,我特别用它来预处理和修饰我的所有Haskell代码。它具有小到足以容易破解的优点,大多数构造不需要明确的monadic符号。相反,语法几乎逐字逐句地阅读。
特别是,我进入了Haskell2010 的词法结构,其思想是以不同的方式为不同的应用程序修改这种语法。我现在通过创建与每个语法构造相对应的标签,并将这些标签传递给每个构造来实现此目的。我还使用这些标签作为Data.Map的键。这允许我在我的语法的不同应用中为各种标签提供后处理。
我的代码的细节并不重要;我的问题的要点应该是明确的,因为我在这里描述的任何类似的应用。这是Haskell2010的语法(草案)片段:
program = Program §
many $ lexeme ∨ whitespace
lexeme = Lexeme §
reservedop ∨ reservedid ∨ qvarid ∨ qconid ∨ qvarsym ∨ qconsym ∨ literal
∨ special
literal = Literal §
integer ∨ float ∨ hchar ∨ hstring
special = Special §
oneOf "(),;[]`{}"
whitespace = Whitespace §
many1 whitestuff
whitestuff = Whitestuff §
whitechar ∨ comment ∨ ncomment
whitechar = Whitechar §
newline ∨ vertab ∨ space ∨ tab ∨ uniWhite
newline = Newline §
hreturn ◊ linefeed ∨ hreturn ∨ linefeed ∨ formfeed
努力使语法简洁,我发现这个重复的样板非常难看。为什么我不能只使用函数名称本身,并让每个函数根据需要访问自己的名称? (操作符是monadic,所以我们有机会在幕后做任何我们喜欢的事情。)
我理解并喜欢用于解释为什么在Lisp(Scheme)中构造“X”或者在Haskell中不需要任何面向对象语言的参数的元游戏,因为一个人只做“Y”。与Haskell相比,Lisp既不那么有纪律,而且看起来更灵活。 Lisp让我想起动画诞生时的早期“墨水瓶外”漫画,一只手可以从屏幕后面出来,重新绘制一些东西,根据需要弯曲规则。
相反,从面向对象的角度来看(就像我试图避免的所有宗教一样),这是对“自我”的一种相当常规的用法。但是,我不想在这里创建一个完整的面向对象的框架,我只想要一点点直接访问符号表(或等效的,无论做什么工作),因为这些其他语言提供单向或另一个。
所以我很尴尬,我不能在这里玩这个元游戏。在我看来,Haskell,整齐而且有很好的纪律,密封了对符号表和运行时环境的访问,这将让我高尔夫这个代码,摆脱这个眼睛的样板。或不?我问这里。
答案 0 :(得分:4)
我认为你不能在符合标准的Haskell中做到这一点,因为这会破坏参照透明度,但使用名为Template Haskell的GHC扩展,可以完成。模板Haskell允许您在编译时运行自定义代码以生成样板代码或执行更有趣的操作(您可能希望转换现有代码以实现目标)。