2010-03-21 52 views
8

我是Haskell中的一名絕對新手,但仍試圖理解它是如何工作的。Haskell,自然數列表

我想寫我自己的惰性整數列表[1,2,3,4,5 ...]。

對於那些名單我已經寫

ones = 1 : ones 

當嘗試,做工精細:

*Main> take 10 ones 
[1,1,1,1,1,1,1,1,1,1] 

我怎麼可以這樣做增加整數?

我都試過,但它確實是失敗:

int = 1 : head[ int + 1] 

此後,我怎麼能作出這樣的相乘兩個流的方法?如:

mulstream s1 s2 = head[s1] * head[s2] : mulstream [tail s1] [tail s2] 
+1

如果你用()替換所有的[],你可能會對()和[]之間的區別感到困惑,因爲你的最後一個例子適用於無限列表。 – 2010-03-21 18:42:39

回答

17

int = 1 : head [ int + 1]不工作的原因是:

  • 頭返回單個元素,但第二個參數:需要是一個列表。
  • int + 1試圖添加一個列表和一個數字,這是不可能的。

創建列表從1計數到無窮大最簡單的方法是[1..]

要在1以外的階數,你可以使用[firstElement, secondElement ..],例如以創建所有正奇數整數的列表:[1,3 ..]

要獲得無限列表[x, f x, f (f x), f (f (f x)),...],您可以使用iterate f x(例如, iterate (*2) 1將返回列表[1, 2, 4, 16,...]

要在每對兩個列表元素的應用操作配對,使用zipWith:

mulstream s1 s2 = zipWith (*) s1 s2 

爲了使這個定義更簡潔,你可以使用免費的點對點形式:

mulstream = zipWith (*) 
11

對於自然數,你必須使用地圖:

num1 = 1 : map (+1) num1 

或者內涵:

num2 = 1 : [x+1 | x <- num2] 

當然還是:

num3 = [1..] 
+3

或者'nat = 1:map succ nat' – sastanin 2010-03-23 16:01:55

2

有語法這在語言版本:

take 10 [1,2..] 

=> [1,2,3,4,5,6,7,8,9,10] 

你甚至可以做不同的步伐:

take 10 [1,3..] 
=> [1,3,5,7,9,11,13,15,17,19] 
3

我米不知道這是你問的,但在我看來,你想要的建立一個不斷增加的自然數列表,而不依賴任何其他列表。因此,通過該令牌,你可以做這樣的事情

incr a = a : inrc (a+1) 
lst = inrc 1 

take 3 lst 
=> [1,2,3] 

,從技術上,被稱爲累積功能(我相信),然後我們所做的就是讓它的一個特殊情況,以「樂善堂」

易於使用

你可以從那裏瘋了,做這樣的事情:

lst = 1 : incr lst where incr a = (head a) + 1 : incr (tail a) 

take 3 lst 
=> [1,2,3] 

等,儘管這可能依賴於一些東西,你不會還沒有學會(哪裏) - 由OP判斷 - 但它應該仍然很容易閱讀。

呵呵,對了,然後列表乘法。那麼,你可以使用zipWith(*)如上面提到的,或者你可以推倒重來這樣的(這是更多的樂趣,相信我:)

lmul a b = (head a * head b) : lmul (tail a) (tail b) 
safemul a b = take (minimum [len a, len b]) (lmul a b) 

原因safemul,我相信,你可以找到通過試驗該功能,但它必須處理'尾巴'。麻煩的是,沒有空的列表,不匹配的列表等等,所以你要麼必須一起破解各種定義(lmul _ [] = []),要麼使用守衛或者在哪裏等等...或堅持zipWith :)