[英]Haskell, recursive function “cannot construct the infinite type”
I'm trying to build a recursive function that will help me solve Project Euler problem 15 in Haskell (I'm very new to it), but the compiler tells me: 我正在尝试构建一个递归函数,以帮助我解决Haskell中的Project Euler 问题15 (我对此非常陌生),但是编译器告诉我:
Occurs check: cannot construct the infinite type: t ~ [t]
Relevant bindings include
grid :: t (bound at 15.hs:1:22)
r :: t (bound at 15.hs:1:17)
d :: t (bound at 15.hs:1:15)
generateTree :: [t] -> t -> [t] (bound at 15.hs:1:1)
In the expression: generateTree [d + 1, r] grid
In the expression:
[generateTree [d + 1, r] grid, generateTree [d, r + 1] grid]
I'm not really too sure whats the problems, and I've come across compilers complaining at me in an easier way to understand. 我不太清楚问题出在哪里,而且我遇到过编译器以一种更容易理解的方式抱怨我。 Here is my function: 这是我的功能:
generateTree (d:r:_) grid
| down && right = [generateTree [d + 1, r] grid, generateTree [d, r + 1] grid]
| down = [generateTree [d + 1, r] grid, -1]
| right = [-1, generateTree [d, r + 1] grid]
| otherwise = [d, r]
where down = elem d [0..grid]
right = elem r [0..grid]
Thanks 谢谢
The reason why you're seeing the error is that you're trying to say that generateTree
returns values like [-1, [-1, [-1, 0]]]
, which doesn't have a valid type in Haskell. 看到错误的原因是,您试图说generateTree
返回的值类似[-1, [-1, [-1, 0]]]
,在Haskell中没有有效的类型。 All values in a list have to have the same type, which means that lists can't be nested like this. 列表中的所有值必须具有相同的类型,这意味着列表不能像这样嵌套。 You could nest it like [[[-1]], [[-1], [-1, 0]]]
, but this would have the type [[[Int]]]
, meaning it could only ever be 3 levels deep. 您可以像[[[-1]], [[-1], [-1, 0]]]
那样嵌套它,但是它的类型为[[[Int]]]
,这意味着它只能是3个级别深。 You want arbitrarily nested levels, so you'll need a new data type that defines such a recursive structure. 您需要任意嵌套的级别,因此您需要一个新的数据类型来定义这种递归结构。
Since your function only ever is returning two elements in a list, you could do this with a binary tree. 由于您的函数只会返回列表中的两个元素,因此可以使用二叉树来实现。 Luckily, this is pretty simple in Haskell: 幸运的是,这在Haskell中非常简单:
data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Eq, Show)
Here Leaf a
represents a single value, and Node left right
represents a split in the tree, so you could have 在这里, Leaf a
表示单个值, Node left right
表示树中的拆分,因此您可以
Node
(Leaf (-1))
(Node
(Leaf (-1))
(Node
(Leaf (-1))
(Leaf 0)
)
)
(whitespace added for clarity) (为清楚起见添加了空格)
Which would be equivalent to the invalid list above of [-1, [-1, [-1, 0]]]
. 这将等效于以上[-1, [-1, [-1, 0]]]
的无效列表。 Is this more verbose? 这更冗长吗? Of course, but it allows arbitrary nesting. 当然,但是它允许任意嵌套。
Now you just have to modify your function definition to use this type: 现在,您只需要修改函数定义即可使用此类型:
generateTree :: Int -> Int -> Int -> Tree Int
generateTree d r grid
| down && right = ...
| down = ...
| right = Node (Leaf (-1)) (generateTree d (r + 1) grid)
| otherwise = Node (Leaf d) (Leaf r)
where
down = d `elem` [0..grid]
right = r `elem` [0..grid]
I'll let you finish the rest of the definition, this is just an example to get you started. 我将让您完成其余的定义,这只是一个入门的示例。
Your generateTree
function returns a list, see: 您的generateTree
函数返回一个列表,请参见:
| otherwise = [d, r]
But What is the type of d
and r
? 但是d
和r
是什么类型? generateTree
returns a list of whatever the generateTree
function returns (all elements in a list must be the same type): generateTree
返回一个generateTree
函数返回的内容的列表(列表中的所有元素必须为相同类型):
| right = [-1, generateTree [d, r + 1] grid]
In other words, your logic is broken. 换句话说,您的逻辑被打破了。 Learn the type system, learn to write the types and then the error will become apparent. 学习类型系统,学习编写类型,然后错误将变得明显。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.