简体   繁体   English

Haskell递归函数“无法构造无限类型”

[英]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 ? 但是dr是什么类型? 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM