2016-10-01 42 views
1

我試圖限定,接受一個點(x,y)的作爲輸入的功能,並返回對應於遞歸調用Haskell的在列表解析無限遞歸

無限列表

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) 

我真的不知道如何使這項工作。任何幫助,將不勝感激!

+4

['迭代P(0,0)'](http://hackage.haskell.org/package/base-4.9.0.0 /docs/Prelude.html#v:iterate)? – Bergi

+2

請不要刪除您的示例代碼。每個人都從某個地方出發。有沒有必要爲此感到羞恥:) – 2016-10-01 18:35:54

+0

@Rhymoid,你是在暗示我的小學標誌,BASIC和Turbo Pascal代碼可能有什麼值得期待的地方嗎?我自己只寫過完美的代碼,我期望其他人也一樣。編程是嚴肅的事務,並且沒有任何錯誤的餘地! – dfeuer

回答

8

讓我們首先忽略你的確切問題,並着重於讓循環工作。你想要什麼,本質上,是有東西,需要一些初始值iv(即(0, 0)(u, v)),並返回列表

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

一些功能f(從p(x, y)構造)。而且,您希望結果重用列表中先前計算的元素。如果我會寫一個函數自己,這樣做,它可能looke這樣的(但也許有些不同的名稱):

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

但是,當然,我會先look如果與類型的函數存在。它確實:它被稱爲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現在有打電話給p(x, y)o的說法和(u, v)該次迭代:

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 

它就是這麼簡單:(x, y)o的定義實際上是在範圍上的where -clause 。你甚至可以決定合併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 
+0

非常感謝!這很有道理! –

0

你想:

  1. 要構建一個列表[(u, v)]與此列表的頭等於(0, 0)
  2. 然後map此列表與功能\(u, v) -> (u^2 - v^2 + x, 2 * u * v + y)該函數的結果附加到列表。

我們可以寫爲描述此功能:

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)] 
+0

你確定這個效率和基於'iterate'的解決方案一樣高效嗎? – 2016-10-02 01:23:53