F#拼接自定义Googol类型列表时FS0001错误原因咨询
错误根因
你的报错核心是参数传值不全导致的函数柯里化遗留问题:
powerInner定义了3个入参:(n:float) (p:float) (acc : list<Googol>),但你在numberInner里调用的时候写的是powerInner n [],只传了2个参数,缺失了幂次初始值p的入参。- F#是默认柯里化的语言,参数传不全的时候不会报错,而是会返回一个「等待接收剩余参数」的函数,你这里返回的就是等待接收
acc参数、类型为Googol list -> Googol list的函数,自然没法和Googol list类型的acc用@拼接,就触发了类型不匹配报错。
其他逻辑错误
你代码里还有一个隐蔽的逻辑错误:powerInner里的match分支写反了匹配对象
// 你现在写的是匹配n match n with | p when p <= 1.0 -> acc | p when p > 1.0 -> ...
这里match的对象是n,分支里的p是新的模式变量,会覆盖你外层传入的幂次参数p,相当于你永远在用n的值判断是否终止递归,完全不符合生成某数所有幂次的逻辑,应该改成匹配p。
关于@操作符的问题
@本身就是F#的内置中缀函数,作用是拼接两个同类型的列表,类型签名为'a list -> 'a list -> 'a list,你这里的用法本身没有问题,报错是因为左边的操作数不是列表而是未完全调用的函数。
修正后可运行的代码
type Googol = { number : float power : float result : float } let generatePowers (n:float) : list<Googol> = let rec powerInner (n:float) (p:float) (acc : list<Googol>) = // 修正:匹配幂次p而非基数n match p with | p when p <= 1.0 -> acc | p when p > 1.0 -> powerInner n (p-1.0) ([{ number=n; power=p; result=n**p}]@acc) let rec numberInner (n:float) (acc : list<Googol>) = match n with | n when n <=1.0 -> acc // 修正:给powerInner补全初始幂次参数,适配欧拉56题b<100的要求 | n when n >1.0 -> numberInner (n-1.0) ((powerInner n 99.0 [])@acc) numberInner n []
如果要适配Project Euler 56题的要求(a<100、b<100),调用的时候直接传generatePowers 99.0即可。
内容的提问来源于stack exchange,提问作者kakakakakakakk
相关产品推荐
相关产品推荐

