繁体   English   中英

列表理解中的 Haskell 无限递归

[英]Haskell infinite recursion in list comprehension

我试图定义一个函数,它接受一个点 (x,y) 作为输入,并返回一个对应于递归调用的无限列表

P = (u^2 − v^2 + x, 2uv + y)

u 和 v 的初始值都是 0。

  • 第一个电话是

    P = (0^2 - 0^2 + 1, 2(0)(0) + 2) = (1,2)

  • 那么结果元组 (1,2) 将是 u 和 v 的下一个值,因此它将是

    P = (1^2 - 2^2 + 1, 2(1)(2) + 2) = (-2,6)

等等。

我想弄清楚如何在 Haskell 中对此进行编码。 这是我到目前为止:

o :: Num a =>(a,a) -> [(a,a)]
o (x,y) = [(a,b)| (a,b)<- [p(x,y)(x,y)]]   
  where p(x,y)(u,v) = ((u^2)-(v^2)+x,(2*u*v)+y)

我真的不知道如何使这项工作。 任何帮助,将不胜感激!

让我们首先忽略您的确切问题,并专注于使循环正常工作。 本质上,您想要的是具有一些初始值iv (即(0, 0) for (u, v) ),并返回列表

f iv : f (f iv) : f (f (f iv)) : f (f (f (f iv))) : ...

对于某些函数f (从您的p(x, y)构建)。 此外,您希望结果重用先前计算的列表元素。 如果我自己编写一个执行此操作的函数,它可能看起来像这样(但可能有一些不同的名称):

looper :: (a -> a) -> a -> [a]
looper f iv = one_result : more_results
  where
    one_result   = f iv
    more_results = looper f one_result

但是,当然,我会首先查看是否存在具有该类型的函数。 它确实:它被称为Data.List.iterate 它唯一做错的是列表的第一个元素将是iv ,但这可以通过使用tail轻松修复(这里很好:只要您的迭代函数终止, iterate将始终生成一个无限列表)。


现在让我们回到你的案例。 我们确定它通常看起来像这样:

o :: Num a => (a, a) -> [(a, a)]
o (x, y) = tail (iterate f iv)
  where
    f (u, v) = undefined
    iv = undefined

正如您所指出的, (u, v)的初始值是(0, 0) ,这就是我们对iv的定义。 f现在必须使用o的参数中的(x, y)和该迭代的(u, v)调用p

o :: Num a => (a, a) -> [(a, a)]
o (x, y) = tail (iterate f iv)
  where
    f (u, v) = p (x, y) (u, v)
    iv = (0, 0)
    p = undefined

就这么简单: o定义中的(x, y)实际上在where子句中的范围内。 你甚至可以决定合并fp ,最后得到

o :: Num a => (a, a) -> [(a, a)]
o (x, y) = tail (iterate p iv)
  where
    iv = (0, 0)
    p (u, v) = (u^2 - v^2 + x, 2 * u * v + y)

另外,我可以建议您将Data.Complex用于您的应用程序吗? 这使得在限制a有点更严格的(你需要RealFloat a ,因为Num.signum ),但在我看来,它使你的代码更容易阅读:

import Data.Complex
import Data.List (iterate)

{- ... -}

o :: Num (Complex a) => Complex a -> [Complex a]
o c = tail (iterate p iv)
  where
    iv = 0  -- or "0 :+ 0", if you want to be explicit
    p z = z^2 + c

你要:

  1. 构造一个列表[(u, v)] ,这个列表的头部等于(0, 0)
  2. 然后使用函数\\(u, v) -> (u^2 - v^2 + x, 2 * u * v + y) map此列表,将此函数的结果附加到列表中。

我们可以像描述的那样编写这个函数:

func :: (Num t) => (t, t) -> [(t, t)]
func (x, y) = (0, 0) : map functionP (func (x, y))
    where functionP (u, v) = (u^2 - v^2 + x, 2 * u * v + y)

GHCi > take 5 $ func (1, 2)
     > [(0,0),(1,2),(-2,6),(-31,-22),(478,1366)]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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