Kahjin’s Weblog

[写真][獣戯画]

未分類 カテゴリーへ kahjin が 11月 29, 2009 に投稿

[和訳]LYHGG2-4

未分類 カテゴリーへ kahjin が 11月 29, 2009 に投稿

http://learnyouahaskell.com/starting-out#an-intro-to-lists

Creative Commons

An intro to lists

Haskellのリストは便利なんだ。データ構造としてよく使われるし、いろんなモデルや解法で使えるんだ※32。リストはとてもすごいんだ※33。このsectionでは、基本的なリスト、文字列(これもリスト)やリストの表記をみていこう※34。Haskellでは、リストはhomogenousなデータ構造なんだ。homogenousって何?ってリストの要素がすべて同じ型のものを言うんだ。この意味はリストの要素がすべてIntegerだったり、characterだったり、まぜこぜはダメだよ。じゃ、リストを分析してみよか※35。Note:GHCIでnameを左辺に定義するとき、letというkeywordを使うんだけど(GHCIではlet a = 1)、これはスクリプトにa=1と書いて、それをロードしてくるのと同じことなんだ。
ghci> let lostNumbers = [4,8,15,16,23,42]
ghci> lostNumbers
[4,8,15,16,23,42]

リストは角括弧[]で書いて、値はカンマで区切るんだ。[1,2,'a',3,'b','c',4]なんてリストを書いたら、Haskellは文字は数字じゃないつーの!と口を挟むんだ(脇道にそれるけど、文字は’(シングルクォート)で挟むのよ)。ちょうど、文字について喋らせてもらうけど、文字列(string)は只の文字(character)のリストだから。”hello”は['h','e','l','l','o']のsyntax sugar(糖衣構文)だから。文字列はリストだから、リストで使える関数を扱い、いろいろと手の込んだことができるという訳。++ operatorを使って、二つのリストを繋げて、一つのリストにしてみようか。

ghci> [1,2,3,4] ++ [9,10,11,12]
[1,2,3,4,9,10,11,12]
ghci> “hello” ++ ” ” ++ “world”
“hello world”
ghci> ['w','o'] ++ ['o','t']
“woot”

++ operatorの使い方を復習しよか。例えば、[1,2,3] ++ [4]のような要素が一つしかないリストが++の左側にきてもうまくいくんだ。処理内部では、Haskellは++の左側をすべて走査するから、左側のリストが長くなっても問題ない。ただ、あまりにも長すぎると(fifty million entries)、走査するのに時間がかかるけどね。

リストの先頭に何かを追加したいのなら、: operatorを使うといいよ(別名:cons operator)。ほら、こんな具合に。

ghci> ‘A’:” SMALL CAT”
“A SMALL CAT”
ghci> 5:[1,2,3,4,5]
[5,1,2,3,4,5]

取説:数字のリストに加えるなら数字を、文字のリストに加えるなら、文字を取ること。++は二つのリストを用意すること。++を使って、リストの後尾に何かを追加したい場合はリストとみなして、[]で囲うこと。

[1,2,3]は1:2:3:[]のsyntax sugarね。[]は空リストのこと。空リストに3を追加すると、[3]になり、それに2を追加すると、[2,3]になるよ。

Note: []と[[]]や[[],[],[]] の違いがわかるかな?空リストと空リストを含むリストね。

リストから値を取り出したかったら、!!を使うといいよ。リストのindexは0からね※36。

ghci> “Steve Buscemi” !! 6
‘B’
ghci> [9.4,33.2,96.2,11.2,23.25] !! 1
33.2

もし、4つしかない要素のリストから6つ目の要素を取り出そうとすると、エラーになるから気をつけてね。

リストはリストを含むことができるんだ。リストを含むリストを含むリスト…※37

ghci> let b = [[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]
ghci> b
[[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]
ghci> b ++ [[1,1,1,1]]
[[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3],[1,1,1,1]]
ghci> [6,6,6]:b
[[6,6,6],[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]
ghci> b !! 2
[1,2,2,3,4]

リストを含むリストは数字だけのリストや文字だけのリストのときにした説明と同様で、型が異なるリストをまぜこぜにできないよ。リストとリストの長さは関係ない。
リストはその中身を比較することもできるんだ。<, <=, > や >= を使うんだけど、それはアルファベット順というか辞書の索引順の規則に従うんだ※38。まず、リストの先頭同士を比較して、同じなら2つ目の要素同士を比較して…

ghci> [3,2,1] > [2,1,0]
True
ghci> [3,2,1] > [2,10,100]
True
ghci> [3,4,2] > [3,4]
True
ghci> [3,4,2] > [2,4]
True
ghci> [3,4,2] == [3,4,2]
True

リストで他にできることないかな?もちろん、あるよ。じゃあ、リストで使える基本的な関数を見てみよう。

  • ※32 listの説明にmultitudeとかbunchを使うのはいいね。イメージがわきやすい。
  • ※33 SOってわざわざ大文字にしてるのかがわからなかった。ソリストってことかいなw 原文抜粋:Lists are SO awesome. LSOで調べたら、ロンドン交響楽団って出てきたわ。リストってもしかしてあのリスト?
  • ※34 list comprehension でリスト内包表記とよく呼ばれる。
  • ※35 and now, a list!
  • ※36 o!  !i
  • ※37 気持ち悪い
  • ※38 lexicographyね。

[調理]イナダ

未分類 カテゴリーへ kahjin が 11月 28, 2009 に投稿

イナダ(ブリの若魚)が手に入ったので、捌いてみました。

地方によって、呼び名が違うんでしたっけ?!よく知りません。



半分は刺身で、もう半分は鍋にしていただきました。

あらを使った料理は今後の課題ですね。さすがに手の込んだ料理は難しいので(汗)。

[散歩][写真][紅葉]

未分類 カテゴリーへ kahjin が 11月 28, 2009 に投稿

[戦況]少年野球

未分類 カテゴリーへ kahjin が 11月 28, 2009 に投稿

さあ、いよいよ残すところ後1回の攻防となりました。6回を終了して、3対3の同点!7回のワンイニングで雌雄を決することになります。

7回の表、Aチームの攻撃。

先頭バッターがレフト前にヒット!そして二盗。後続打者が送りバントでワンナウト3塁。三遊間を抜けるか抜けないかのゴロの間に、3塁走者がホームに生還。

Aチーム勝ち越し!4対3で7回裏に移ります。Aチームは0点で抑えること、Bチームは同点か勝ち越しサヨナラにしたいところです。

7回の裏、Bチームの攻撃。

先頭バッタ-が三遊間にゴロを打った。が、しか〜し!打球を捕った遊撃手が1塁悪送球。バッターはそのまま2塁へ進塁。ノーアウト2塁、一打同点!あわよくばサヨナラだ!後続バッターは手堅くバンドで、ワンナウト3塁。表と似たような展開だ!おお!三遊間抜けた!レフト前ヒット!走者生還。4対4同点だ。

Bチーム同点に追いついた。しかし、追加点は入らず。試合はサドンデスに突入!

Aチームの攻撃。ワンナウト満塁から。

「3点以上は点がほしい場面ですね。」と某経験者は語るが、果たしてどうか。

Aチームはファーボールの押し出し1点のみ。ここぞの一本が出ない。

俄然、有利になったBチーム。もう、ここで決めるしかない!

先頭打者でいきなり、ワイルドピッチ!1点追加。もうあと1点で勝利だ。

次はスクイズを敢行だ。3塁走者がホームに返ってくる。やった!が、打者のインタフェアにより得点は無効。なんという、つかの間の喜び。なんで後が続かないのだ!

結局、Bチームもワイルドピッチの1点のみ。

サドンデス2回目に突入だ!ここまでこじれた試合はあっただろうか。全くいつ終わるかわからない。

Aチームの攻撃。センター前ポテンヒットで1点追加。再度、某経験者は語る。「もう2点はほしいですね」願い虚しく、1点で攻撃終了。サドンデスも2回までのため、Bチームは1点でも入れれば、とりあえずここでの負けはなくなるぞ。

Bチームの攻撃。ピッチャー後方の二遊間のところに小フライがあがった!二塁手が捕球の体勢に入るが、これをファンブル!!当然、各走者は捕球するものとの思いから、帰塁していたが、慌てて走り出す。二塁手がこぼれたボールを拾い上げ、3塁へ送球!これは、ゲッツーを狙えたのに勿体ないぞ。インフィールドフライの疑いもあるが、その間に、3塁走者はホームに生還していた!1点ゲット。同点だ。しかし、またしてもここまで。

サドンデスでも決着つかず!!勝敗は抽選に持ち込まれた!

果たして、どちらのチームが勝つのか!

<<<>>>

この流れだとどちらのチームが勝ったと思いますか?

昔のことをちょっと思い出したりして、胸が熱くなりました。

内容はともかくとして、両チームにありがとうといいたい。

[散歩][写真]

未分類 カテゴリーへ kahjin が 11月 28, 2009 に投稿

[散歩][写真]

未分類 カテゴリーへ kahjin が 11月 28, 2009 に投稿

[散歩][写真][紅葉]

未分類 カテゴリーへ kahjin が 11月 28, 2009 に投稿

[和訳]LYHGG2-3

未分類 カテゴリーへ kahjin が 11月 28, 2009 に投稿

http://learnyouahaskell.com/starting-out#babys-first-functions

Creative Commons

Baby’s first functions

前のsectionで、関数を呼ぶ方法が掴めたと思うんだけど、今から自分でそれを作ろう。お気に入りのtext editorを開いて、数を受け取ったらそれを2倍にする関数を書いて。

doubleMe x = x + x

関数はそれを呼ぶときと似たような方法で定義するんだ。関数名の後に、受け取るパラメタを空白で定義するんだ。それで、関数が定義できたら、=の後に実際にその関数が何をするのか書くんだ。じゃあ、それをbaby.hsとか何かに保存して。保存できたら、そのファイルを保存した場所でghciを起動してみよう。GHCIの世界に入ったら、:l babyで作ったファイルをloadすると、自分で作った関数で遊べるようになるよ。

ghci> :l baby
[1 of 1] Compiling Main ( baby.hs, interpreted )
Ok, modules loaded: Main.
ghci> doubleMe 9
18
ghci> doubleMe 8.3
16.6

+関数はIntegerであれ、floating-point numberであれ、数と見なされるものであれば、どんな数でもうまくいくんだ。二つのパラメタをそれぞれ二乗して足す(二乗和)関数を作ってみよう。

doubleUs x y = x*2 + y*2

簡単でしょ。doubleUs x y = x + x + y + yでも定義できたんだけど、これだと結果が予測しやすいし、試してみてその結果を確認するのも楽だよね。これをbaby.hsに追記して、保存して、GHCIの世界で:l babyでloadしよう。

ghci> doubleUs 4 9
26
ghci> doubleUs 2.3 34.2
73.0
ghci> doubleUs 28 88 + doubleMe 123
478

思ったとおりに関数が呼び出せた?doubleUs関数はこんな風に定義できることも気に掛けておいてね。

doubleUs x y = doubleMe x + doubleMe y

簡単な例なんだけど、これがまさしくHaskellを通して見た日常の風景なんだ。簡単な関数から作っていって、しかもそれが正しく動いて、それらを組み合わせてより複雑な関数を作るんだ。繰り返しも避けられるしね。もし、実際は2倍じゃなくて3倍にしないとダメだとわかったら、プログラムをどう変更するかな?きっとdoubleMe関数をx + x + xと変更するだろうね。しかもdoubleUs関数でdoubleMe関数を呼んでたりすると… 次元の狭間でもうまくいくと思うよ※30。

関数の定義した順番なんて特に気にしなくてもいいよ。doubleMe関数がDoubleUs関数より先に定義されていようといまいと問題ないから。

次は、100以下のときは数を2倍にする関数を作ってみよう。100より大きい場合はそのままでいいよね。だってそのままでも十分大きいんだから。

doubleSmallNumber x = if x > 100
                        then x
                        else x*2

右側はHaskellのstatement(文)を導入したんだ。他の言語を使ったことあるなら、if文はお馴染みだよね。ここでの大きな違いはHaskellだとelse部分は必須だということ。他の言語だとif文の条件が満たされないと、その後の処理が飛ばされてしまうことがあるんだけど、Haskellはすべての式や関数は絶対に何かを返さないといけない。if文も一行で書けるんだけど、こっちの方が読みやすいよね。Haskellではif文のようなものを別名:expressionと呼んでいるんだ※31。expressionは基本的になにかしらの値を返すコード(a piece of code)なんだ。5も5という値を返すexpressionだし、4 + 8もexpression、x + yもxとyの合計を返すexpressionなんだ。さっきもelse部分は必須って言ったよね?逆説的かもしれないけど、statementが値を返すっていったら、それはexpressionなんだ。さっきの関数のすべての値に1を加えたかったら、こんな風に書くんだ。

doubleSmallNumber’ x = (if x > 100 then x else x*2) + 1

丸括弧がなかったら、xが100以下のときしか+1されないよ。あ、そうだ。関数名の最後にある’(アポストロフィ)はHaskellの構文上特に意味はないんだけど、遅延評価しない関数を定義したときや関数やパラメタを微妙に修正したりしたときに見分ける方法として付けるんだ。別に関数名の中にあってもちゃんと文字として使えるよ。

conanO’Brien = ”It’s a-me, Conan O’Brien!”

ここで注意点が2つあります。1つ目は関数名は大文字で始めない。例えば、ConanO’とかね。これは後で詳しく理由を説明するよ。2つ目はパラメタを受け取らない関数はdefinition (or a name)とか言ったりするんだ。一度定義したnameやfunctionはどんな変更も受け付けない。この例だと、conanO’Brienと文字列の”It’s a-me, Conan O’Brien!”は可換的に使用できるんだ。

  • ※30 ただし、彷徨うことになるのは明白。
  • ※31 別名になっていないんだけど、どうしたものか。表現式とするか迷うね。<exp>とかに略したいわ。

[散歩][写真][風]

未分類 カテゴリーへ kahjin が 11月 23, 2009 に投稿