Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中的递归不动点函数_Haskell - Fatal编程技术网

Haskell中的递归不动点函数

Haskell中的递归不动点函数,haskell,Haskell,我试图创建一个函数,在保持递归调用值列表的同时,在x=fx的情况下找到函数的不动点。我在将递归调用附加到上一个列表的部分遇到问题。这是我到目前为止的代码-谢谢 fixpointL :: (Int -> Int) -> Int -> [Int] fixpointL f x | x == (f x) = [x] | otherwise = [x ++ fixpointL f (f x)] 检查类型: x :: Int fixpointL f (f x)

我试图创建一个函数,在保持递归调用值列表的同时,在x=fx的情况下找到函数的不动点。我在将递归调用附加到上一个列表的部分遇到问题。这是我到目前为止的代码-谢谢

fixpointL :: (Int -> Int) -> Int -> [Int]
fixpointL f x | x == (f x) = [x]
              | otherwise = [x ++ fixpointL f (f x)]
检查类型:

x :: Int
fixpointL f (f x) :: [Int]
(++) :: [a] -> [a] -> [a]
这条线应该是x:fixpointlfx

请记住,我还没有测试它,你能发布一个你想测试的函数吗?

检查类型:

x :: Int
fixpointL f (f x) :: [Int]
(++) :: [a] -> [a] -> [a]
这条线应该是x:fixpointlfx


请记住,我还没有测试过它,你能发布一个你想测试的函数吗?

你没有分享到底是什么不起作用-Haskell的编译时错误有时看起来有点难以理解,但如果你知道如何解释它们,它们总是充满了信息。这里的错误是:

<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)]
也就是说,它接受两个可以容纳任何元素的列表,并返回另一个相同类型的列表。Int当然不是列表,所以GHC不能理解这一点也就不足为奇了。 至于第二个错误,它告诉您表达式x++fixpointL fx应该是Int,但实际上是list[Int]。后者是因为它本质上是假装您将修复第一个错误,并将x转换为它期望的[Int]——那么表达式x++fixpointL f x实际上将是一个Int列表,即[Int]。但你把它括在方括号里:

[x ++ fixpointL f (f x)]
这意味着一个只包含一个元素的列表,该元素是x++fixpointlfx,正如我刚才解释的,它目前被假定为[Int]类型。但由于这是函数的返回值,并且您已将返回类型声明为[Int],这意味着[…]的内容必须为零或多个值(在本例中为Int类型之一)。因此,这就解释了另一种类型不匹配的原因

我们怎样才能修复它们?似乎您想要获取fixpointL f x的输出-我们假设它是您的类型签名所说的int的列表,所以这是GHC必须假设的,并将起始值x附加到它的前面。假设您想使用++运算符,编写此代码的正确方法如下:

[x] ++ fixPointL f (f x)
这将获取只包含x的单例列表和递归调用的结果,并将它们放在一个列表中。这种类型检查、编译并按预期工作:

Prelude> fixpointL (^2) 1
[1]
Prelude> fixpointL (*2) 1
[1,2,4,8,16,32,64,128,256,512,...]
显然,在第二个例子中,我尽可能快地终止了它,之前的实际输出要长得多,但你明白了

改进函数的最后一种方法是使用cons运算符:,其目的是在列表的开头添加一个元素,而无需首先构造单例列表。由于Haskell的列表是简单的链表,其中每个元素都包含一个指向下一个元素的指针,因此这始终是一个有效的操作,而不是将项目追加到末尾,这需要与列表长度成比例的时间。虽然这里的性能差异很小,但它仍然被认为更为惯用。这是一个实用的、惯用的版本:

fixpointL :: (Int -> Int) -> Int -> [Int]
fixpointL f x | x == (f x) = [x]
              | otherwise = x : fixpointL f (f x)

你没有分享什么是不起作用的——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)]
也就是说,它接受两个可以容纳任何元素的列表,并返回另一个相同类型的列表。Int当然不是列表,所以GHC不能理解这一点也就不足为奇了。 至于第二个错误,它告诉您表达式x++fixpointL fx应该是Int,但实际上是list[Int]。后者是因为它本质上是假装您将修复第一个错误,并将x转换为它期望的[Int]——那么表达式x++fixpointL f x实际上将是一个Int列表,即[Int]。但你把它括在方括号里:

[x ++ fixpointL f (f x)]
这意味着一个只包含一个元素的列表,该元素是x++fixpointlfx,正如我刚才解释的,它目前被假定为[Int]类型。但由于这是函数的返回值,并且您已将返回类型声明为[Int],这意味着[…]的内容必须为零或多个值(在本例中为Int类型之一)。因此,这就解释了另一种类型不匹配的原因

我们怎样才能修复它们?似乎您想要获取fixpointL f x的输出-我们假设它是您的类型签名所说的int的列表,所以这是GHC必须假设的,并将起始值x附加到它的前面。假设运算符要使用的正确方式是:

[x] ++ fixPointL f (f x)
这将获取只包含x的单例列表和递归调用的结果,并将它们放在一个列表中。这种类型检查、编译并按预期工作:

Prelude> fixpointL (^2) 1
[1]
Prelude> fixpointL (*2) 1
[1,2,4,8,16,32,64,128,256,512,...]
显然,在第二个示例中,我尽可能快地终止了它,之前的实际输出要长得多,但是 你明白了

改进函数的最后一种方法是使用cons运算符:,其目的是在列表的开头添加一个元素,而无需首先构造单例列表。由于Haskell的列表是简单的链表,其中每个元素都包含一个指向下一个元素的指针,因此这始终是一个有效的操作,而不是将项目追加到末尾,这需要与列表长度成比例的时间。虽然这里的性能差异很小,但它仍然被认为更为惯用。这是一个实用的、惯用的版本:

fixpointL :: (Int -> Int) -> Int -> [Int]
fixpointL f x | x == (f x) = [x]
              | otherwise = x : fixpointL f (f x)