2016-08-18 9 views
3

は、私たちがリストhaskellはどのようにして別のリストから新しいリストを作成しますか?

x = [1..10] 

を持っており、私たちは、このように、これを使用して別のリストyを作成しようとするとします

y= [a|a<-x] 

のでxからリストyを作成しながら、それはxの各要素にアクセスします(1〜10)、同じ順序でyに挿入します。 haskellのリストは単独でリンクされたリストなので、新しい要素をその先頭に挿入することができます。まず、[1][] &に1を挿入します。次に、それは[2,1]を持っているので、それは[2,1]を持っているので、&の頭に2を挿入します。その後、我々は[3,2,1] &を持っている3 &を挿入します。最終的にy[10,9..1]とする必要があります。代わりにy[1..10]とします。どうしてこんなことに?

+1

これは、リストの理解構文を解消する方法の良い説明です。http://stackoverflow.com/a/8029698/1013393 – sjakobi

答えて

6

リストの尾でも「挿入」、それらを(リストが構築されている間)、ないヘッド(参照:「末尾再帰のモジュロ短所」)ので:

[a | a <- [1..10]]  == 
[a | a <- (1:[2..10])] ==  -- [a | a <- ([1] ++ [2..10])] 
1 : [a | a <- [2..10]]   -- [1] ++ [a | a <- [2..10]] 

これが原因

です
[a | a <- (xs ++ ys)] == [a | a <- xs] ++ [a | a <- ys] 

[a | a <- ys] == ys 
6

リストカンプを考えている方法rehensionsはあまり正確ではありません。理解が分かると、(最初は空の)結果リストの先頭に連続した結果が追加されていると考えるべきではありません。

代わりに、xの残りの部分でリスト内包表記を実行した結果の前にそれぞれf aが追加されていると考えてください。それは

[f a | a <- x:xs] == f x : [f a | a <- xs] 

これは再帰的なアプローチである、である - 結果リストは、リストの最後尾のために存在すると仮定することによって、あなたはそれの前に次の結果を追加することができます。

4

リストの理解度が、モナディック計算に嫌なのは、直感を使って動作するのではなく、正確にどのように見ていくのが有益なのです。

[a | a <- [1..3]] == do {a <- [1..3]; return a} -- desugared comprehension 
        == [1..3] >>= return a   -- desugared do 
        == concat (map return [1..3]) -- definition of >>= 
        == concat [[1], [2], [3]]  -- defintiion of return 
        == [1,2,3]      -- definition of concat 
関連する問題