我正在尝试创建一个函数,该函数查找函数f
(在x = f x
的情况下)的固定点,同时保持值列表的递归调用。我在将递归调用追加到上一个列表的过程中遇到了麻烦。到目前为止,这是我的代码-谢谢!
fixpointL :: (Int -> Int) -> Int -> [Int]
fixpointL f x | x == (f x) = [x]
| otherwise = [x ++ fixpointL f (f x)]
答案 0 :(得分:5)
您没有分享完全不起作用的内容-Haskell(或更确切地说,GHC)的编译时错误有时看起来有些难以理解,但如果您知道如何解释它们,则总是充满信息。这里的错误是:
<interactive>:4:30: error:
* Couldn't match expected type `[Int]' with actual type `Int'
* In the first argument of `(++)', namely `x'
In the expression: x ++ fixpointL f (f x)
In the expression: [x ++ fixpointL f (f x)]
<interactive>:4:30: error:
* Couldn't match expected type `Int' with actual type `[Int]'
* In the expression: x ++ fixpointL f (f x)
In the expression: [x ++ fixpointL f (f x)]
In an equation for `fixpointL':
fixpointL f x
| x == (f x) = [x]
| otherwise = [x ++ fixpointL f (f x)]
如您所见,类型不匹配有两个不同的错误-但实际上它们密切相关。两者都很清楚到底出了什么问题。
在第一个中,它抱怨x
中的x ++ fixpointL f (f x)
应该是[Int]
(Int
的列表),但实际上是{ {1}}。这很有道理-Int
是赋予该函数的第二个参数,类型签名宣称该参数为x
。但是您正在尝试对其应用Int
运算符,并且该运算符的类型为:
(++)
Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
当然不是列表,因此也难怪GHC无法理解这一点。第二个错误-告诉您表达式Int
应该是x ++ fixpointL f (f x)
,但实际上是一个列表(Int
)。后者是因为它实际上是在假装您将解决第一个错误,并将[Int]
放入期望的x
中-这样,表达式[Int]
的确是{{1}的列表} s(即x ++ fixpointL f (f x)
)。但是,您已经将其括在方括号中:
Int
表示仅包含一个元素的列表,该元素为[Int]
,正如我刚才解释的那样,当前假定其类型为[x ++ fixpointL f (f x)]
。但是,由于这是函数的返回值,并且您已将返回类型声明为x ++ fixpointL f (f x)
,所以这意味着[Int]
的内容必须为零个或多个值(在这种情况下为一个),类型为[Int]
。这样可以解释另一种类型的不匹配。
我们如何解决它们?看来您想获取[...]
的输出-我们假设它是Int
的列表(您的类型签名表明是这样,因此GHC必须假定)。并将起始值fixpointL f (f x)
附加到它的前面。假设要使用Int
运算符,则正确的编写方式如下:
x
这将获取仅包含(++)
的单例列表以及递归调用的结果,并将它们放到一个列表中。这种类型的检查,编译和运行符合预期:
[x] ++ fixPointL f (f x)
(很明显,在第二个示例中,我会尽快将其杀死,在我可以使用之前,实际输出要长得多,但是您明白了。)
可以改善功能的最后一种方法是使用“ cons”运算符x
,其目的是在列表的开头添加元素,而无需首先构造单例列表。由于Haskell的列表是简单的链接列表,其中每个元素都包含指向下一个的指针,因此这始终是一种高效的操作(与将项目追加到末尾相对,后者花费的时间与列表的长度成正比)。尽管此处的性能差异很小,但仍被认为是惯用的。这是正常的工作版本:
Prelude> fixpointL (^2) 1
[1]
Prelude> fixpointL (*2) 1
[1,2,4,8,16,32,64,128,256,512,...]
答案 1 :(得分:1)
检查类型:
x :: Int
fixpointL f (f x) :: [Int]
(++) :: [a] -> [a] -> [a]
x ++ fixpointL f (f x) :: ??????????
[????] :: ?????
该行应为x : fixpointL f (f x)
请记住,我尚未测试过,您可以发布要测试的功能吗?