成らぬは人の為さぬなりけり

エンジニアライフをエンジョイする為のブログ

すごいHaskellたのしく学んでみる-その2

前回からの続きです。

今日のテーマは…

  • リスト内包表記
  • タプル

以上!短いw


まずは、

リスト内包表記

リストのフィルタリング・変換、組み合わせを行う方法、だそうです。


リスト内包表記ってなんぞや、と最初は思いましたが、
やってみると非常にわかりやすい。
リストを書くノリで、「どういうリストなのか」を書いちゃおうぜ、的な。


早速、ghciで書いてみます。

Prelude> [ x*2 | x <- [1..20]]
[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40]

「1から20までの数字を2倍した数のリスト」です。
わかりやすい。(気がするのは私だけでしょうか)


条件(述語、というらしい)を付けることもできます。

Prelude> [ x | x <- [1..20], even x]
[2,4,6,8,10,12,14,16,18,20]

「1から20までの偶数のリスト」です。
「even」は受け取った値が偶数か否かをBoolで返してくれます。


述語は複数つけられます。

Prelude> [ x | x <- [1..20], even x, x > 10]
[12,14,16,18,20]


さらに、2つのリストを組み合わせる事もできます。

Prelude> [ x+y | x <- [1,2,3], y <- [10,20,30,40] ]
[11,21,31,41,12,22,32,42,13,23,33,43]

この場合、
[1,2,3]

[10,20,30,40]
の総当りになります。
つまり

Prelude> [1+10, 1+20, 1+30, 1+40, 2+10, 2+20, 2+30, 2+40, 3+10, 3+20, 3+30, 3+40]
[11,21,31,41,12,22,32,42,13,23,33,43]

こういうことになります。


次のテーマに移ります。

タプル

タプルは他の言語でもよく見るものなので、馴染みはあります。
haskellは、タプルの要素の個数とその型の組み合わせでタプルの型が決まります。

以下の例は、同じサイズ2のタプルですが、型が違います。

Prelude> :t (1,2)
(1,2) :: (Num t1, Num t) => (t, t1)
Prelude> :t (1,'a')
(1,'a') :: Num t => (t, Char)

なので、こういうことは出来ません。

Prelude> [(1,2),(1,'a')]

<interactive>:24:5:
    No instance for (Num Char)
      arising from the literal `2'
    Possible fix: add an instance declaration for (Num Char)
    In the expression: 2
    In the expression: (1, 2)
    In the expression: [(1, 2), (1, 'a')]


では、次にzip関数を使って、タプルのリストを作ってみます。

Prelude> zip [1,2,3] [10,20,30,40]
[(1,10),(2,20),(3,30)]

リスト要素は全て同じ型でなければならないので、
素数が少ない方に合わせたサイズの新しいリストが生成されています。
なるほど。


リストの要素の型が全て同じであれば良いので、
数値リストと文字列リストをzipすることはできます。

Prelude> zip [1,2,3] ["hoge","foo","bar"]
[(1,"hoge"),(2,"foo"),(3,"bar")]


さらに面白かったのが、haskellはデフォルトで遅延評価なので、
無限リストと有限リストがzipできるという点です。

Prelude> zip [1..] ["hoge","foo","bar"]
[(1,"hoge"),(2,"foo"),(3,"bar")]

「1から無限」のリストと文字列のリストをzipしています。
「1から無限」のリストが必要な時に必要なだけ評価されている、感じでしょうか。
これはカッコイイ。


最後に、今日(実は昨日)の勉強のまとめとして、

  • リスト内包表記
  • タプル
  • パターンマッチ

を使って、ちょっと計算をしてみたいと思います。

Prelude> sum [ x + y | (x, y) <- zip [1,3..] [2,4..10]]
55

明日からは、Haskellの型について!
オブジェクト指向で言うクラスとは違う概念、というのが未だ良くわかっていないです、、
がんばります。