SML中('a,'b) reader与类型元组的语法差异咨询
('a,'b) reader类型的解释 首先要明确SML里两种完全不同的语法:
逗号分隔的括号
('a,'b)是类型参数列表:这是用来声明多态类型别名的参数,和值层面的元组没有关系。就像你给出的代码里,('a,'b) reader是一个接受两个类型参数的多态类型别名——'a是读取操作返回的值的类型,'b是输入状态的类型。星号
*是值元组的类型语法:a * b确实对应Haskell的(a,b),表示一个包含a类型值和b类型值的元组,这是值层面的类型,和类型参数的声明语法完全不搭边。
为什么不能写成('a * 'b) reader?
如果写成('a * 'b) reader,意味着reader是一个只接受单个元组类型参数的类型别名,但我们需要的是两个独立的类型参数:一个是要读取的结果类型'a,另一个是状态的类型'b。把它们合并成'a * 'b作为单个参数的话,类型别名的语义就完全变了——它不再表示“从状态'b读取'a”,而是变成了“从某个未知类型读取'a * 'b”,这和原本的'b -> ('a * 'b) option的语义完全不符。
举个具体的实例:当你把类型实例化为(int, string) reader时,它展开后是string -> (int * string) option,也就是“从字符串状态里读取一个整数,同时返回新的字符串状态(或失败)”,这正是典型的读取器模式的语义。如果写成(int * string) reader,那展开后的类型会变成'c -> ((int * string) * 'c) option(这里'c是未知的状态类型),完全不是我们想要的。
另外可以对比Haskell的写法:Haskell里对应的读取器类型是type Reader r a = r -> Maybe (a, r),这里r和a是两个独立的类型参数,SML只是把类型参数放在了类型名前面的括号里,用逗号分隔,本质和Haskell的多态类型参数是一个意思,只是语法风格不同。
内容的提问来源于stack exchange,提问作者RandomB

