计算正整数除数列表时的类型错误如何修复?
OCaml函数类型不匹配问题解决
题目要求
定义函数
libDiv,用于计算某个正整数的自然数除数列表。
首先定义libDivInf,要求libDivInf n i返回n的所有小于等于i的除数列表,其类型标注为:
libDivInf : int -> int -> int list
示例:
(liDivInf 20 4) = [4;2;1] (liDivInf 7 5) = [1] (liDivInf 4 4) = [4;2;1]
尝试代码
let liDivInf : int -> int -> int list = function (n,i) -> if i = 0 then [] (*ERROR LINE*) else if (n mod i) = 0 (* if n is dividable by i *) then i::liDivInf n(i-1) else liDivInf n(i-1);; let liDiv : int -> int list = function n -> liDivInf n n;;
错误信息
ERROR: this pattern matches values of type 'a * 'b ,but a pattern was expected which matches values of type int
错误原因
这个错误的核心是类型不匹配:
- 你用
function (n,i)的写法,是在匹配元组类型('a * 'b),也就是把参数当作一个包含两个元素的元组来处理。 - 但你给
liDivInf标注的类型是int -> int -> int list,这是柯里化的双参数函数,OCaml中柯里化函数和元组参数函数属于不同的类型分支,因此编译器报错。
另外还有一个语法错误:liDivInf n(i-1)会被OCaml解析为「把n当作函数,传入i-1作为参数」,正确的函数调用应该用空格分隔参数:liDivInf n (i-1)。
修复方案
因为题目明确要求libDivInf的类型是int -> int -> int list,所以推荐采用保持柯里化类型的修复方式:
修复后的代码
let liDivInf : int -> int -> int list = fun n i -> if i = 0 then [] else if (n mod i) = 0 then i :: liDivInf n (i-1) else liDivInf n (i-1);; let liDiv : int -> int list = function n -> liDivInf n n;;
说明
- 把
function (n,i)改成fun n i ->,符合柯里化函数的参数定义方式,和标注的类型完全匹配。 - 修正函数调用写法,将
liDivInf n(i-1)改为liDivInf n (i-1),确保OCaml正确识别是调用liDivInf并传入两个参数n和i-1。
内容的提问来源于stack exchange,提问作者Axq
相关产品推荐
相关产品推荐

