Wednesday, July 23, 2014

Haskell part1

Haskell

ここを流し読みしながらghciで試している。
ErlangにHaskellにgoと節操が無いけど、仕事じゃないからいいのさ。関数型言語は面白いな。

リストの操作

関数型言語ってリストの操作が便利すぎる。
基本的な使い勝手はErlangと似ている。Haskellのほうが覚える量が多そうだけど。

要素の追加

リストの先頭に要素を追加。
*Main> 1:2:3:4:[]
*Main> [1]:[2]:[3]:[4]:[[]]
最後は[]でリスト対して追加することを明示しないと落ちる。
追加する要素は追加されるリスト内の要素と同じ形でないといけない。例えば1:2:3:4:[[]]とすると落ちる。

要素の取り出し

*Main> [1,2,3,4,5] !! 2
*Main> [[1,2,3],[4,5]] !! 1 !! 1
!!の後にindexを指定する。indexは0から始まる。
リストが入れ子になっている場合は!!を連続して書ける。上の例だと1番目の要素(リスト内)の1番目の要素を指定している。

リスト同士の比較

*Main> [1,0,3] > [1]
True
*Main> [1,0,3] > [2]
False
先頭要素から順番に比較。同じ値が続いた場合、要素が多いほうが大きいとみなされるみたいだ。

head, tail, last, init

*Main> head [1,2,3,4]
1
*Main> tail [1,2,3,4]
[2,3,4]
*Main> last [1,2,3,4]
4
*Main> init [1,2,3,4]
[1,2,3]
シンプルって素晴らしい。空のリストについて上記コマンドはあまねく例外(empty list)になる。

length

*Main> length [1..3]
3
リストの長さ。

null

*Main> null []
True
*Main> null [1,2]
False
リストが空ならTrue、それ以外はFalse。

take

*Main> take 10 [1..10]
[1,2,3,4,5,6,7,8,9,10]
*Main> take 100 [1..10]
[1,2,3,4,5,6,7,8,9,10]
*Main> take 2 [1..10]
[1,2]
*Main> take 0 [1..10]
[]
リストから指定した個数だけ引っ張りだす。リストより大きな数を指定した場合、リスト全部ゲットだぜ。

drop

*Main> drop 0 [1..10]
[1,2,3,4,5,6,7,8,9,10]
*Main> drop 2 [1..10]
[3,4,5,6,7,8,9,10]
*Main> drop 100 [1..10]
[]
リストから指定した個数だけ廃棄して残りを返す。リストより大きな数を指定した場合、全部廃棄して空になる。

maximum, minimum, sum, product

*Main> maximum [1..10]
10
*Main> minimum [1..10]
1
*Main> sum [1..10]
55
*Main> product [1..10]
3628800
*Main> product []
1
*Main> sum [sum [1..2], sum [3..4]]
10
*Main> [sum [1..2], sum [3..4]]
[3, 7]
maximum, mimimumはリストが多重でも結果が出るが、空のリストを与えると例外(empty list)。sum, productはこの逆パターン。product []は1なのね。

レンジ指定

Haskellのレンジ指定はかっこよすぎる。

*Main> [5,7..20]
[5,7,9,11,13,15,17,19]
1から始まり2刻みで10までのリスト。
*Main> [20,18..0]
[20,18,16,14,12,10,8,6,4,2,0]

降順もいける。

*Main> take 10 (cycle [1,2,3])
[1,2,3,1,2,3,1,2,3,1]

[1,2,3]の繰り返しの数列から先頭10個を取る。遅延評価だから無限数列を定義して利用できる。

cycleとは別に指定した要素を繰り返し続けるrepeat





<div class="se-section-delimiter"></div>
*Main> take 5 (repeat 5)
[5,5,5,5,5]
*Main> take 5 (repeat [1,5])
[[1,5],[1,5],[1,5],[1,5],[1,5]]





<div class="se-section-delimiter"></div>

### 条件付のリスト定義

こういうの、数学屋さんはなじみ深いんだろうなあ。





<div class="se-section-delimiter"></div>
*Main> [x*2 | x <- [1..10], mod x 2 == 0]
[4,8,12,16,20]

x*2なリストで、x110の範囲でかつ残余が0なもの。





<div class="se-section-delimiter"></div>
*Main> [ x*y | x <- [1..10], mod x 2 == 0, y <- take 5 (repeat 5)]
[10,10,10,10,10,20,20,20,20,20,30,30,30,30,30,40,40,40,40,40,50,50,50,50,50]

パラメータを複数与えると条件に合致するものの、あらゆる組み合わせの配列が得られる。





<div class="se-section-delimiter"></div>
*Main> [x ++ ” ” ++ y | x <- [“yukari”, “maki”, “zunko”], y <- [“run”, “s
ep”, “awake”, “boomed”, “fun”, “take”]]
[“yukari run”,”yukari sleep”,”yukari awake”,”yukari boomed”,”yukari fun”,
ukari take”,”maki run”,”maki sleep”,”maki awake”,”maki boomed”,”maki fun”
maki take”,”zunko run”,”zunko sleep”,”zunko awake”,”zunko boomed”,”zunko
n”,”zunko take”]

文字列に対しても同様の定義が可能。名詞と動詞のあらゆる組み合わせを簡単に表現できる。





<div class="se-section-delimiter"></div>

#### 大文字、小文字の排除

文字列はCでいうところのchar型の配列(リスト)なので、条件付きリストとして表現できる。





<div class="se-section-delimiter"></div>

```haskell
removeNonUppercase st = [c | c <- st, elem c ['A'..'Z']]
removeUppercase st = [c | c <- st, elem c ['a'..'z']]
大文字、小文字を排除する関数。
*Main> removeNonUppercase "Yuzuki Yukari"
"YY"
*Main> removeUppercase "Yuzuki Yukari"
"uzukiukari

多重リストに対する条件付きリストの生成

*Main> let xxs = [[1,5,3,6],[1,4,6,1,8],[12,4,23,52,11]]
*Main> xxs
[[1,5,3,6],[1,4,6,1,8],[12,4,23,52,11]]
*Main> [[x | x <- xs, even x] | xs <- xxs]
[[6],[4,6,8],[12,4,52]]
条件側も入れ子にして頑張れる。
  • xsにxxsの各要素を入れて、
  • xs(これもリスト)の各要素の中でeven xを満たすものだけピックアップ
要は2重リストの中から偶数だけを取り出す。
Written with StackEdit.

No comments:

Post a Comment