サーチ…


構文

  1. 空のリストコンストラクタ

    [] :: [a]

  2. 空でないリストコンストラクタ

    (:) :: a -> [a] -> [a]

  3. head - リストの最初の値を返す

    head :: [a] -> a

  4. last - リストの最後の値を返す

    last :: [a] -> a

  5. tail - 最初の項目のないリストを返す

    tail :: [a] -> [a]

  6. init - 最後の項目がないリストを返す

    init :: [a] -> [a]

  7. xs !! i - リストxsのインデックスiで要素を返す

    (!!) :: Int -> [a] -> a

  8. take n xs - リストの最初のn個の要素を含む新しいリストを返すxs

    take :: Int -> [a] -> [a]

  9. map ::(a - > b) - > [a] - > [b]

  10. filter ::(a - > Bool) - > [a] - > [a]

  11. (++):: [a] - > [a]

  12. concat :: [[a]] - > [a]

備考

  1. [a][] aと等価です。
  2. []空のリストを作成します。
  3. []関数定義LHSで、例えばf [] = ... 、空のリストパターンです。
  4. x:xsは、要素xがリストの先頭に追加されたリストを作成しますxs
  5. f (x:xs) = ...は空でないリストのパターンマッチで、 xは頭、 xsはテールです。
  6. f (a:b:cs) = ...f (a:(b:cs)) = ...は同じです。それらは、最初の要素がaであり、2番目の要素がbであり、リストの残りがcsである少なくとも2つの要素のリストのパターン一致です。
  7. f ((a:as):bs) = ...f (a:(as:bs)) = ...と同じではありません。前者はリストの非空リスト、用のパターンマッチで、ヘッドのヘッドであるa asヘッドの尾部であり、 bs尾です。
  8. f (x:[]) = ...f [x] = ...は同じです。これらは正確に1つの要素のリストのパターンマッチです。
  9. f (a:b:[]) = ...f [a,b] = ...は同じです。これらは正確に2つの要素のリストのパターンマッチです。
  10. f [a:b] = ...は、要素がリストでもある正確に1つの要素のリストのパターンマッチです。 aは要素の先頭、 bは要素の末尾です。
  11. [a,b,c](a:b:c:[])と同じです。標準リスト表記法は、 (:)[]コンストラクタの文法的な砂糖です。
  12. もう一度(x:y:ys)を繰り返す代わりに、リスト全体をall (または選択した他の名前)として参照するために、 all@(x:y:ys)all@(x:y:ys)使用することができます。

リストリテラル

emptyList     = []

singletonList = [0]               -- = 0 : []

listOfNums    = [1, 2, 3]         -- = 1 : 2 : [3]

listOfStrings = ["A", "B", "C"]

リストの連結

listA      = [1, 2, 3]

listB      = [4, 5, 6]

listAThenB = listA ++ listB       -- [1, 2, 3, 4, 5, 6]

(++) xs     [] = xs
(++) []     ys = ys
(++) (x:xs) ys = x : (xs ++ ys)

リストの基礎

Haskell Preludeのリストの型コンストラクタは[]です。 Int型の値を保持するリストの型宣言は、次のように記述されます。

xs :: [Int]    -- or equivalently, but less conveniently,
xs :: [] Int

Haskellのリストは同質の系列です。つまり、すべての要素が同じ型でなければなりません。タプルとは異なり、リストタイプは長さの影響を受けません:

[1,2,3]   :: [Int]
[1,2,3,4] :: [Int]

リストは2つのコンストラクタを使用して構築されます:

  • []は空のリストを作成します。

  • (:) 、 "cons"と発音され、要素をリストの前に付加します。コンスのx (タイプの値a上に)、 xs (同じタイプの値のリストa )、そのヘッド (第1要素)である新しいリスト作成x 、及び尾部 (残りの要素)であるxs

以下のような簡単なリストを定義することができます:

ys :: [a]
ys = []

xs :: [Int]
xs = 12 : (99 : (37 : []))   
-- or  = 12 : 99 : 37 : []     -- ((:) is right-associative)
-- or  = [12, 99, 37]          -- (syntactic sugar for lists)

リストの作成に使用できる(++)(:)[]観点から再帰的に定義されています。

リストの処理

リストを処理するには、単純にリスト型のコンストラクタのパターンマッチングを行うことができます:

listSum :: [Int] -> Int
listSum []          = 0
listSum (x:xs) = x + listSum xs

もっと複雑なパターンを指定することで、より多くの値を一致させることができます。

sumTwoPer :: [Int] -> Int
sumTwoPer [] = 0
sumTwoPer (x1:x2:xs) = x1 + x2 + sumTwoPer xs
sumTwoPer (x:xs) = x + sumTwoPer xs

上記の例では、奇数長のリストが引数として指定されたケースを処理するために、より網羅的なパターンマッチングを提供する必要がありました。

Haskell Preludeは、 mapfilterなどのリストを扱うための多くの組み込み関数を定義しています。可能であれば、独自の再帰関数を記述するのではなく、これらを使うべきです。

リストの要素へのアクセス

リストのn番目の要素にアクセスする(ゼロから始まる):

list = [1 .. 10]

firstElement = list !! 0           -- 1

注意してください!!部分的な関数なので、特定の入力はエラーを生成します:

list !! (-1)     -- *** Exception: Prelude.!!: negative index  

list !! 1000     -- *** Exception: Prelude.!!: index too large

Data.List.genericIndexもあります!! Integral値をインデックスとして受け取ります。

import Data.List (genericIndex)

list `genericIndex` 4              -- 5

単一リンクリストとして実装された場合、これらの操作はO(n)時間かかる。インデックスで頻繁に要素にアクセスする場合は、( ベクトルパッケージの) Data.Vectorやその他のデータ構造を使用する方がよいでしょう。

レンジ

1から10までのリストを作成するには、範囲表記法を使用するのが簡単です。

[1..10]    -- [1,2,3,4,5,6,7,8,9,10]

ステップを指定するには、コンマと次の要素をstart要素の後に追加します。

[1,3..10]  -- [1,3,5,7,9]

ハスケルは常にステップ間の算術的な違いとしてステップをとり、最初の2つ以上の要素と上限を指定することはできないことに注意してください。

[1,3,5..10] -- error
[1,3,9..20] -- error

範囲を降順で生成するには、常に負のステップを指定します。

[5..1]     -- []

[5,4..1]   -- [5,4,3,2,1]

Haskellは厳密ではないので、リストの要素は必要な場合にのみ評価され、無限リストを使うことができます。 [1..][1..]から始まる無限のリストです。このリストは変数にバインドすることも、関数の引数として渡すこともできます。

take 5 [1..]   -- returns [1,2,3,4,5] even though [1..] is infinite

丸めの問題を回避するために、浮動小数点値を含む範囲を使用するときは、最大で半分の差分を受け入れるため注意が必要です。

[1.0,1.5..2.4]    -- [1.0,1.5,2.0,2.5] , though 2.5 > 2.4

[1.0,1.1..1.2]    -- [1.0,1.1,1.2000000000000002] , though 1.2000000000000002 > 1.2

範囲は数値だけでなく、 Enum型の型クラスを実装するすべての型で機能します。いくつかの列挙可能な変数abcと、範囲構文はこれらのEnumメソッドを呼び出すのと同じです。

[a..]    == enumFrom a
[a..c]   == enumFromTo a c
[a,b..]  == enumFromThen a b
[a,b..c] == enumFromThenTo a b c

たとえば、 Boolでは

 [False ..]      -- [False,True]

False後にスペースがあることに注意して、これがモジュール名の修飾として解析されないようにしてください( False..はモジュールFalseから解析され. )。

リストの基本機能

head [1..10]       --    1

last [1..20]       --    20

tail [1..5]        --    [2, 3, 4, 5]

init [1..5]        --    [1, 2, 3, 4]

length [1 .. 10]   --    10

reverse [1 .. 10]  --    [10, 9 .. 1]

take 5 [1, 2 .. ]  --    [1, 2, 3, 4, 5]

drop 5 [1 .. 10]   --    [6, 7, 8, 9, 10]

concat [[1,2], [], [4]]   --    [1,2,4]

折りたたみ

これは、左折がどのように実装されているかです。 step関数の引数の順序がfoldr (右折)と比べてどのように反転しているかに注目してください。

foldl :: (b -> a -> b) -> b -> [a] -> b
foldl f acc []     =  acc
foldl f acc (x:xs) =  foldl f (f acc x) xs         -- = foldl f (acc `f` x) xs  

左の折りたたみfoldlは左に関連付けられます。あれは:

foldl (+) 0 [1, 2, 3]     -- is equivalent to ((0 + 1) + 2) + 3

理由は、 foldlは次のように評価される( foldlの帰納的ステップを参照)。

foldl (+) 0 [1, 2, 3]                        --  foldl (+)    0   [ 1,   2,   3 ]
foldl (+) ((+) 0 1) [2, 3]                   --  foldl (+)   (0 + 1)   [ 2,   3 ]
foldl (+) ((+) ((+) 0 1) 2) [3]              --  foldl (+)  ((0 + 1) + 2)   [ 3 ]
foldl (+) ((+) ((+) ((+) 0 1) 2) 3) []       --  foldl (+) (((0 + 1) + 2) + 3) []
((+) ((+) ((+) 0 1) 2) 3)                    --            (((0 + 1) + 2) + 3)

最後の行は、 ((0 + 1) + 2) + 3と等価です。これは、 (fab)が一般的に(a `f` b) (fab)と同じであり、したがって((+) 0 1)が特に(0 + 1)と同じであるためです。

折りたたみ

これは、右折がどのように実装されるかです:

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z []     = z
foldr f z (x:xs) = f x (foldr f z xs)              -- = x `f` foldr f z xs

右の折りたたみfoldrは右に関連付けられます。あれは:

foldr (+) 0 [1, 2, 3]      -- is equivalent to 1 + (2 + (3 + 0))

理由はfoldrが次のように評価されるからです( foldr誘導ステップを見てください)。

foldr (+) 0 [1, 2, 3]                        --          foldr (+) 0  [1,2,3]
(+) 1 (foldr (+) 0 [2, 3])                   -- 1 +        foldr (+) 0  [2,3]
(+) 1 ((+) 2 (foldr (+) 0 [3]))              -- 1 + (2 +     foldr (+) 0  [3])
(+) 1 ((+) 2 ((+) 3 (foldr (+) 0 [])))       -- 1 + (2 + (3 +  foldr (+) 0 []))
(+) 1 ((+) 2 ((+) 3 0))                      -- 1 + (2 + (3 +            0   ))

最後の行は、 ((+) 3 0)(3 + 0)と同じであるため、 1 + (2 + (3 + 0))に相当します。

`map`を使った変換

しばしば、コレクションの内容(リスト、またはトラバース可能なもの)を変換または変換することを望みます。ハスケルではmapを使用しmap

 -- Simple add 1
 map (+ 1) [1,2,3]
 [2,3,4]
 
 map odd [1,2,3]
 [True,False,True]
 
 data Gender = Male | Female deriving Show
 data Person = Person String Gender Int deriving Show

 -- Extract just the age from a list of people
 map (\(Person n g a) -> a) [(Person "Alex" Male 31),(Person "Ellie" Female 29)]
 [31,29]

`filter`によるフィルタリング

与えられたリスト:

 li = [1,2,3,4,5]

filter ::( filter :: (a -> Bool) -> [a] -> [a]を使用して述語でリストをフィルタリングできます。

 filter (== 1) li       -- [1]
 
 filter (even) li       -- [2,4]
 
 filter (odd) li        -- [1,3,5]
 
 -- Something slightly more complicated
 comfy i = notTooLarge && isEven
   where 
      notTooLarge = (i + 1) < 5
      isEven = even i
 
 filter comfy li        -- [2]

もちろん、数字だけではありません。

 data Gender = Male | Female deriving Show
 data Person = Person String Gender Int deriving Show
 
 onlyLadies :: [Person] -> Person
 onlyLadies x = filter isFemale x
   where 
     isFemale (Person _ Female _) = True
     isFemale _ = False
 
 onlyLadies [(Person "Alex" Male 31),(Person "Ellie" Female 29)]
 -- [Person "Ellie" Female 29]

リストの圧縮と解凍

zipは2つのリストを取り、対応するペアのリストを返します。

zip []     _      = []
zip _      []     = []
zip (a:as) (b:bs) = (a,b) : zip as bs

> zip [1,3,5] [2,4,6]
> [(1,2),(3,4),(5,6)]

関数で2つのリストを圧縮する:

zipWith f  []     _      = []
zipWith f  _      []     = []
zipWith f  (a:as) (b:bs) = f a b : zipWith f as bs

> zipWith (+) [1,3,5] [2,4,6]
> [3,7,11]

リストの解凍:

unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])

> unzip [(1,2),(3,4),(5,6)]
> ([1,3,5],[2,4,6])


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow