基本类型驱动的ppx重写

时间:2015-08-24 02:16:17

标签: ocaml metaprogramming

我正在写我的第一个ppx扩展名。这个想法是支持多态print函数,类似于Haskell中的show

(我知道存在其他更强大的解决方案,但我希望了解更多有关其工作原理的方法。)

我采用的方法与描述的方法here非常相似:我有一个查找%[print <expr>]标记的映射器,然后用{{1}的字符串表示替换它们}。例如,

<expr>

这适用于常量表达式,但我想支持任意表达式代替[%print 1] ==> string_of_int 1 [%print "aksljd"] ==> "aksljd" 。它应该用最终类型的打印机包装它们。

我目前的做法是使用<expr>Typecore.type_expression转换为Parsetree.expression,然后匹配Typedtree.expression的{​​{1}}字段并确定用...替换整个表达式。例如,对于类型exp_type,我会将Typedtree.expression替换为type test = A of int | B of string[%print A 1]必须按惯例存在。)

这不起作用,因为show_test (A 1)将类型环境作为参数,而我无法获得当前类型的环境&#39;在重写时,因为类型检查甚至还没有执行,然后...... show_test导致Typecore.type_expression导致[%print 1 + 1],应该这样做。

有没有人有解决方案?如果我完全朝着错误的方向前进,请随意指出这一点。 :P

2 个答案:

答案 0 :(得分:3)

评论中的讨论摘要:Haskell中的show并不像这样(并且不能)。 Haskell中的Show a =>将被转换为OCaml中的显式模块参数。该模块的值为print : a -> string。 Haskell通过查找您(或库)已声明的Show的{​​{1}}实例来推断此模块参数,但在OCaml中,您必须手动传递该模块。在Haskell中声明a实例类似于在OCaml中实例化一个仿函数。

在Haskell和OCaml中,在问题中预处理表达式在以下情况下具有可疑含义:

Show

如果let f x = [%print x] (即没有Haskell类型类实例可用且没有传递OCaml模块)。

为了使其更加完整,许多其他分析类型的ppx重写器从类型定义或声明生成代码,而不是从表达式生成代码。

答案 1 :(得分:2)

ppx基本上不支持你想要做的事情。正如您所指出的,ppx在解析之后,尚未完成类型检查。 由于编译器的当前架构,很难键入检查任意表达式。

如果您想要破解,可以阅读this。 :) 作者将在2周的ocaml研讨会上做一个关于它的演示,应该有一个视频。

相关问题