13

私は 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]

その後、2 つのストリームを乗算するメソッドを作成するにはどうすればよいでしょうか? そのような:

mulstream s1 s2 = head[s1] * head[s2] : mulstream [tail s1] [tail s2]
4

5 に答える 5

21

int = 1 : head [ int + 1]うまくいかない理由は次のとおりです。

  • head は単一の要素を返しますが、2 番目の引数:はリストである必要があります。
  • 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,...]

2 つのリストの要素の各ペアに対して操作をペアごとに適用するには、zipWith を使用します。

mulstream s1 s2 = zipWith (*) s1 s2

この定義をより簡潔にするために、ポイントフリー形式を使用できます。

mulstream = zipWith (*)
于 2010-03-21T13:08:12.453 に答える
21

自然数の場合、マップを使用する必要があります:

num1 = 1 : map (+1) num1

または理解:

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

またはもちろん:

num3 = [1..]
于 2010-03-21T13:14:31.783 に答える
5

これがあなたが求めていたものかどうかはわかりませんが、他のリストに依存せずに、増加する自然数のリストを作成したかったように思えます。したがって、そのトークンによって、次のようなことができます

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

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

lst技術的には、これは累積関数と呼ばれ (私は信じています)、「 」で簡単に使用できる特別なケースを作成するだけです。

そこから気が狂って、次のようなことをすることができます:

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  
  | null a || null b  =  []
  | otherwise
         = (head a * head b) : safemul (tail a) (tail b)

の理由はsafemul、関数 を試してみればわかると思いますがlmul、' tail' (および ' head' も同様) に関係しています。問題は、空のリスト、不一致のリストなどのケースがないため、lmulさまざまな定義を一緒にハックする ( lmul _ [] = []) か、ガードなどを使用するかwhere、または に固執する必要があることですzipWith。 )

于 2010-03-21T14:54:06.590 に答える
4

言語にはこれの構文があります。

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]
于 2010-03-21T14:38:56.917 に答える
0

次のように、特定の数までの 1 のリストを定義し、前者をそのまま (など) にして、最初の数を 2 番目に合計することができます。

naturals :: Integer -> [Integer]
naturals n
  | n <= 0    = []
  | otherwise = nat n []
    where
      nat 1 a = (1:a)
      nat n a = nat (n-k) (nat k a)
        where
          k = (n-1)

sumOf :: [Integer] -> [Integer]
sumOf l = sof l []
  where
    sof [] a = a
    sof (x:[]) a = (x:a)
    sof (x:y:zs) a = sof (x:a) (sof ((x+y):zs) a)

それらはすべて 1 であるため、合計の順序を変更することで、左から右、中間点など、好きなようにインクリメントできます。以下を使用して、これを最大 100 (またはそれ以上) テストできます。

(sumOf . naturals) 100

編集: 洗練された内容については、Will Ness による以下のコメントをお読みください。

于 2021-10-23T23:20:13.633 に答える