SML/NJ实现单子解析库时datatype与type别名未按预期工作
问题解答
核心原因
你代码中先后对'a parse_result做了两次定义,SML中后出现的同名类型定义会覆盖之前的定义:
- 第一次使用
type声明别名:type 'a parse_result = 'a parse_data list,此时该类型确实是('a * char list) list的等价别名 - 后续使用
datatype定义代数数据类型时,再次使用了parse_result作为类型名,直接覆盖了之前的别名定义。且本次定义中ParseSuccess of 'a parse_result递归引用的是新定义的ADT本身,而非你预期的列表类型,因此会出现列表和ADT类型不匹配的报错。
解决方案
只要给列表别名和结果ADT设置不同的名称,避免重名覆盖即可,示例定义如下:
type 'a parse_data = ('a * char list); (* 给成功返回的列表类型单独设置别名,不和ADT重名 *) type 'a parse_success = 'a parse_data list; type 'a parser = char list -> 'a parse_success; (* 结果ADT使用独立名称 *) datatype 'a parse_result = ParseFailure | ParseSuccess of 'a parse_success;
调整后使用方式如下:
(* 标注为parse_success即可匹配列表类型 *) val success_data = [("a", [#"a"]), ("b", [#"b"])] : string parse_success; (* 构造ADT时使用parse_result类型 *) val final_result = ParseSuccess success_data : string parse_result;
你之前修改定义后可以正常运行,本质是直接将ADT构造子的参数指定为列表类型,规避了重名覆盖的冲突。
内容的提问来源于stack exchange,提问作者Zelphir Kaltstahl
相关产品推荐
相关产品推荐

