我的经验是,直观地为每个术语加糖似乎没有吸引力,但值得追求。
对持久存储的兴趣使我绕道而行,以考虑混合表达式和原子值的问题。为了支持这一点,我决定在类型系统中将它们完全分开;因此 Int、Char 等是仅用于整数和字符值的类型构造函数。表达式类型由多态类型构造函数 Exp 构成;例如,Exp Int 指的是一步减少到 Int 的值。
当我们考虑评估时,就会出现这与您的问题的相关性。在底层,有些原语需要原子值:COND、addInt 等。有些人将此称为强制表达式,我更愿意将其简单地视为不同类型值之间的强制转换。
挑战在于看看这是否可以在不需要明确的缩减指令的情况下完成。一个解决方案正是您所建议的:即将强制视为一种重载形式。
假设我们有一个输入脚本:foo x
然后,加糖后,变成:(coerce foo) (coerce x)
哪里,非正式地:
coerce :: a -> b
coerce x = REDUCE (cast x) if a and b are incompatible
x otherwise
因此,强制是身份或强制转换的应用,其中b是给定上下文的返回类型。
cast现在可以被视为类型类方法,例如
class Cast a, b where {cast :: a -> b };
-- ¬:: is an operator, literally meaning: don’t cast
--(!) is the reduction operator. Perform one stage of reduction.
-- Reduce on demand
instance Cast Exp c, c where { inline cast = ¬::(!)(\x::(Exp c) -> ¬::(!)x) };
¬::
注释用于抑制强制语法糖化。
目的是Cast
可以引入其他实例来扩展转换范围,尽管我没有对此进行探索。正如你所说,重叠的实例似乎是必要的。