Haskell无法构造无限类型:a0=[a0]
我试图用Haskell解决Euler项目的第二个问题。这个问题相当直截了当——将偶数斐波那契数之和小于4000000。(我是强迫症患者,我正在实现一个稍微修改的函数——一个允许仲裁限制的函数) 我最初的代码是:Haskell无法构造无限类型:a0=[a0],haskell,Haskell,我试图用Haskell解决Euler项目的第二个问题。这个问题相当直截了当——将偶数斐波那契数之和小于4000000。(我是强迫症患者,我正在实现一个稍微修改的函数——一个允许仲裁限制的函数) 我最初的代码是: euler2 limit (num1:num2) |(num1>limit) = 0 |((num2>limit) && ((mod num1 2) == 0)) = num1 |(num2>limit) = 0 |((
euler2 limit (num1:num2)
|(num1>limit) = 0
|((num2>limit) && ((mod num1 2) == 0)) = num1
|(num2>limit) = 0
|(((mod num1 2) == 0) && ((mod num2 2) == 0)) = num1+num2+(euler2 limit [num1+num2,num1+num2+num2])
|((mod num1 2) == 0) = num1+(euler2 limit [num1+num2,num1+num2+num2])
|((mod num2 2) == 0) = num2+(euler2 limit [num1+num2,num1+num2+num2])
|otherwise = euler2 limit [num1+num2,num1+num2+num2]
euler2 limit [] = euler2 limit [1,2]
这导致了以下错误:
发生检查:无法构造无限类型:a0=[a0]
在“(>)”的第二个参数中,即“limit”
在`(&&&)`的第一个参数中,即`(num2>limit)`
在表达式中:((num2>limit)&&((mod num1 2)==0))
现在,通过一些尝试和错误,我意识到它正在尝试将num2
作为一个列表进行类型转换,下面是一个小改动:
euler2 limit (num1:num2:[]) | (num1 > limit) = 0
解决了这个问题。我的问题是为什么?发生了什么?为什么拒绝将num1
和num2
转换为int?类型为(:)
(:) :: a -> [a] -> [a]
如果你有一个模式匹配
euler2 limit (num1:num2)
名称num1
和num2
绑定到构造函数的相应参数(:)
(如果提供的参数是非空列表),因此num2
是元素类型为num1
的列表
如果你匹配
(num1:num2:[])
这是隐含的括号
(num1 : (num2 : []))
现在,
num2:[]
与作为顶级(:)
的第二个参数的列表匹配,匹配成功,将num2
绑定到第二个列表元素,如果提供的参数是正好包含两个元素的列表。请尝试向euler2函数添加显式类型签名:euler2::Integer[Integer]
(或类似的…)。修复类型可能会导致更简单的错误消息。num1
是一个Int
,您的问题是num2
不是;这是一个int
的列表。正确但明确地指出:[]感觉像是一个肮脏的黑客。有没有办法更优雅地执行这类事情?“哈斯凯尔之路”是什么?@AbrahamP[num1,num2]
@AbrahamP为什么(:[])
上的模式匹配会是一个难题?在数据结构上分支是模式匹配的目的。关于最后一个问题:Haskell永远不会隐式强制类型。如果需要,可以使用head
提取num2
的第一个元素,但不能保证在这种情况下调用head
是安全的。只需添加(:)运算符/列表构造函数的隐式右关联性是由于其右固定性