无标签最终风格迷你语言中类型变量歧义问题求解
无标签最终解释器:语句类型歧义问题的解决
问题原因
你遇到的类型歧义,核心是GHC无法将qprint参数的表达式类型,与SynStmt e s约束中的e关联起来:
- 对于
ex01,类型签名(SynExpr e) => e明确了所有lit、add构造的表达式都属于同一个e,GHC能直接统一类型变量,无需额外标注。 - 对于
st01,原签名(SynStmt e s, SynExpr e) => s中,qprint的参数表达式是一个独立的类型变量e0,GHC无法推断e0就是约束中的e,因此抛出歧义错误。
解决方案
要让语句示例像表达式示例一样通用,需要明确绑定表达式的类型与SynStmt约束中的e,有两种简洁的方式:
方式1:使用类型标注绑定表达式类型
直接给表达式加上:: e的类型标注,告诉GHC这个表达式的类型就是SynStmt约束里的e:
st01 :: (SynStmt e s) => s st01 = qprint (add (add (lit 1) (lit 2)) (lit 3) :: e)
方式2:使用ScopedTypeVariables显式约束
借助ScopedTypeVariables扩展,在类型签名中显式声明forall e s,让表达式中的类型变量与约束中的变量统一:
st01 :: forall e s. (SynStmt e s) => s st01 = qprint (add (add (lit 1 :: e) (lit 2)) (lit 3))
验证效果
修改后,st01可以像ex01一样被不同解释器执行,比如用你现有的QuickPrint解释器测试:
-- >>> printstmt st01 -- "qprint ((1 + 2) + 3)"
这个修改保留了无标签最终风格的通用性——只要实现了对应SynStmt e s和SynExpr e的实例,st01就能被该解释器处理。
内容的提问来源于stack exchange,提问作者Jogger
相关产品推荐
相关产品推荐

