静岡Developers勉強会 第5回Haskell読書会に参加しました。

静岡Developers勉強会 第5回Haskell読書会に参加した皆さんお疲れ様でした。発表者のふるたさんも、お疲れ様でした。reverse関数の定義で用いたトランプの例えが、関数の動作をイメージしやすかったと思います。
http://farm5.static.flickr.com/4022/4651361303_7f20245756.jpg

講義録について

今回は勉強会に参加しながら復習した部分を中心に載せていきます。なお、見出しの番号はテキストの通し番号に揃えてあります。

2.4 Haskellプログラム
  • レイアウト規則
    • whereを使ってレイアウト規則を使う場合、where節を用いる定義よりも一文字インデントを下げる。
a = b + c
 where
 a = 1
 b = 2
3.8 多重化型定義
  • クラス制約
    • C a
      • 「C」はクラス名
      • 「a」は型変数
4.4 パターンマッチ
  • リスト・パターン
    • 演算子「:」は「cons演算子」と呼ばれ、既存のリストの先頭に新しい要素を追加することで新しいリストを作成する。

6.6 再帰の秘訣

ここが、今回の勉強会の「肝」だったと感じています。

  • 関数プログラミングの肝
    • 型を意識することで、適応できる数値型を決定する。
    • 単位元・基底部を意識することで、計算が停止し、エラーが発生しない関数を定義できる。
      • 0や1を引数で取る場合
      • 空リストを引数で取る場合
    • 単位元・基底部ではない場合を定義することで、単位元・基底部以外の数値に対する計算方法を定義できる。
    • 上記計算方法を定義することで、適応できる型を増やすことができる。
      • 何を計算する関数か定義することで関数が扱える数値を拡張
    • 出来上がった定義を単純化することで関数を見やすくする。
その他
  • リストのインデックスは0から始まる。
  • 簡約とは、関数を適用することで、これ以上簡単な式にできない形へ変換すること。
    • これ以上、関数を適用できない状態のこと

今後の会場について

2次会で、富士市ご当地グルメ「つけナポリタン」で盛り上がりました。スパゲッティではなくあくまでもラーメン。今後の会場として、富士市に11時過ぎぐらいに集合して、つけナポリタン食べてから勉強会を開くのはいかがでしょう?

オマケ

チーズケーキに隠し味として酒粕が入っていたらしいですが、隠れすぎて見つけられなかったのは内緒です。でも、濃厚な味でまた食べたくなりました。

http://farm5.static.flickr.com/4039/4651359615_ffa1413e3c.jpg

http://farm5.static.flickr.com/4058/4651359863_750850a585.jpg

静岡Developers勉強会 第4回Haskell読書会に参加しました。

静岡Developers勉強会 第4回Haskell読書会に参加した皆さんお疲れ様でした。

http://farm5.static.flickr.com/4033/4547322085_4ae2b91111.jpg

講義録について

前の生成器の値を、後の生成器の値として利用できる

Hugs> [ (x, y) | x <- [1..3], y <- [x..3]]
[(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)]
  • xsはxのセットだからxs
  • xssはxsのセットだからxss

なるほど。

問. 2つのサイコロの出目の組み合わせの数を、リスト内容を使って求めよ。

Hugs> length [(x,y)| x<- [1..6],y<- [1..6]]
36

問.組のリストから各組の2番目の要素を取り出すsecondsを定義せよ。

seconds    :: [(a,b)] -> [b]
seconds ps =  [ y | ( _ , y ) <- ps]

Main> seconds [(2,3),(3,3),(4,2)]
[3,3,2]

ワイルドカードを使って、捨て変数を使うという考え方がHaskellらしい考え方ですね。

練習問題

問1.

sumOne2Hundred = sum [ x*x | x <- [1..100]]

問2.
ここでもワイルドカードを使い、n回繰り返すのは[1..n]の値を捨てるという考えに基づく。
ワイルドカードのn個の値に持つリストに、xを代入するという考え」。

myreplicate :: Int -> a -> [a]
myreplicate n x = [x | _ <- [1..n]] 

yを捨て変数として計算する方法もある。ただし、変数を何も使用しないとエラーが出ることがある。

myreplicate :: Int -> a -> [a]
myreplicate n x = [x | y <- [1..n]] 

無限のリストを生成し、takeで必要な分だけ取る方法もある。

myreplicate2 :: Int -> a -> [a]
myreplicate2 n x = take n (repeat x)

今後、使う約数を求める関数factorsを定義する。

factors :: Int -> [Int]
factors n = [x| x <- [1..n], n `mod` x == 0]

関数factorsを用いて、整数が素数か否かを判定する関数primeを定義する。

prime :: Int -> [Int]
prime n = factors n == [1,n]

この関数primeを用いて2つの場合を計算する。

Main> prime 2147483646
False

2の倍数なので、factorsが[1,2,]を返した時点で、遅延評価で値が返る。

Main> prime 2147483647
^C{Interrupted!}

値は返ってこない。いつまでたっても返ってこない。

ガードの話

ガードがTrueの場合のみ、値をリストに追加する。
ある値までの素数を返す関数primesを定義する。ここでは、関数primeをガードとして利用している。

primes   :: Int -> [Int]
primes n =  [ x | x <- [2..n], prime x]
Main> primes 1 #処理系が空リストを返す
[]
Main> primes 2
[2]
Main> primes 3
[2,3]
Main> primes 4
[2,3]
Main> primes 5
[2,3,5]

ハッシュのような使い方ができる関数findを定義する

find ::Eq a => a -> [(a,b)] -> [b]
find k t = [v | (k',v) <- t, k == k'] 
Main> find '2' [('2',5),('1',3),('2',1),('3',4)]
[5,1]

リストの隣の値との組を生成する関数pairsを定義する。

pairs    :: [a] -> [(a,a)]
pairs xs =  zip xs ( tail xs )
Main> pairs [1,2,3,4]
[(1,2),(2,3),(3,4)]

あるキーがリストのどの位置にあるかを出力する関数positionsは次のとおり。

positions :: Eq a => a -> [a] -> [Int]
positions x xs = [i | (x',i) <- zip xs [0..n], x == x']
                 where n = length xs - 1
Main> positions False [True,False,True,False]
[1,3]
練習問題その2

問3.

pyths :: Int -> [(Int,Int,Int)]
pyths n = [(x,y,z)| x <- [1..n],y <- [1..n], z <- [1..n],x^2 + y^2 == z^2]
Main> pyths 10
[(3,4,5),(4,3,5),(6,8,10),(8,6,10)]

問4.

factors   :: Int -> [Int]
factors n =  [x | x <- [1..n], n`mod`x == 0] 

perfects   :: Int -> [Int]
perfects n =  [x | x <- [1..n], sum (init (factors x)) == x]

問5.

concat2 = concat[[(x,y) | y <- [4,5,6]] |x <- [1,2,3]]

外側のxから評価しているのでいいのかな?

問6.

find     :: Eq a => a -> [(a,b)] -> [b]
find k t =  [v | (k', v) <- t, k == k']

positions      :: Eq a => a -> [a] -> [Int]
positions x xs =  find x (zip xs [0..n])
                  where  n = length xs - 1 

問7.

scalarproduct :: [Int] -> [Int] -> Int
scalarproduct xs ys = sum [x*y |(x,y) <- zip xs ys]

今後について

次回の静岡Developers勉強会 第5回Haskell読書会は静岡で開催。Ustreamして、webから見てもらうのはいかがでしょう?
遠い先の話ですが、「Haskell読書会が終わった後、何をするか。」と帰りの電車の中でやじゅさんと話していました。
個人的にはアルゴリズムの本を読みたいのですが、Erlangなど別の関数型言語を学ぶのもいいですね。でも、一番よいのは、こういった「集まる場所」があるということで、今日は落ち着きました。

オマケ

今週は写真が保存されていなかったため、おやすみ。

静岡Developers勉強会 第3回Haskell読書会に参加しました。

静岡Developers勉強会 第3回Haskell読書会に参加した皆さんお疲れ様でした。

講師として発表

http://farm5.static.flickr.com/4020/4467020674_8830873a2f.jpg
今日は私が講師として発表者しました。久しぶりの発表で、MacKeynoteを使ったセッティング等、トラブルもありましたが、無事に発表することができました。発表資料を、以下のとおりslideshareにupしたのでご参考にしてもらえると幸いです。

参考図書使用のお薦め

使用図書は、後の章まで進んだ際に「なるほど」と理解できる場合が多いので、少しぐらい分からなくても「後で分かる!」と思って進みましょう。第4章はその印象が強い章でした。*1
また、原著が英語であり、訳書であるためなのか、使用図書は理解が難しい表現がある*2ため、参考図書を購入して、並行して読み進める方がよろしいかと思います。ちなみに私はこの本を使いました。

ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門

ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門

講義録について

発表していて印象に残ったコメントを残しておきます。

  • Hoogle
    • Haskellのsourceが掲載。
    • pred関数の実装は、使用図書の掲載方法と異なってた

sourceを当たりたいときはこちらを閲覧します。

λ式を使うと確かに名前を定義する必要はなくなるが可読性は落ちる

そのとおりだと思います。使い分けが大事ですね。

  • 高階関数は、関数を引数に取れる。
  • セクションは演算子を関数として扱うため、引数はセクションの後方にとる。

この2つの説明があって、セクションの節の意味が分かりました。

  • 英語の原本を読むとよい。

この本は大学の講義向けですね。ちなみに、著者のサイトはこちら

LTについて

Supakiyさん、初めてのLTお疲れ様でした。私が思うtwitterの魅力は、「その人の生の声が直接リアルタイムで聞けること」だと思います。ぜひ、LTの感想をblogに書いてほしいです。

ちなみに、私もこっそりLT用資料を用意していたので、せっかくだから貼りつけておきますね。

今後について

次回の静岡Developers勉強会 第4回Haskell読書会は三島で開催!
また、横浜でもふつうのHaskellプログラミング読書会があるそうなので、「ぜひustしてもらいたい!」と思ってます。

オマケ

プリンを食す一コマ。講義中には甘いものを食べて、適度に休憩を入れると、集中力が増しますね。
http://farm5.static.flickr.com/4042/4466246695_e4928560be.jpg

*1:その代わり、要復習です。

*2:訳者も第13章などでは分かりやすい表記には変更しているとのことです。

第2回静岡Developers勉強会 Haskell読書会に参加しました。

第二回Haskell読書会開催のお知らせ - 静岡Developer's 勉強会に参加した皆さんお疲れ様でした。
http://farm3.static.flickr.com/2722/4391099137_d99f03ea89.jpg
今日の講義で私が取ったメモとそれに対するコメントを残しておきますので、ご参考にしてもらえると幸いです。
*1

  • hugsで処理系での実行
    • Hugs> :type "2"
    • "2" :: String
  • 別の処理系での実行
    • :type "2"
    • "2" :: [Char]

処理系によってCharのリストとして認識する場合もあるんですね。

StringはCharのリスト

へぇー。

  • 固定精度整数Int
    • 32bitで表現できるのは-2^31<= x < 2^31
  • Stringを要素に持つリスト

Charのリストを要素に持つリストになるんですね。教科書と違うなぁ。

  • Stringを要素に持つタプル

こちらも、Charのリストを要素に持つリストになります。
Hugsでは要素になるとCharのリストになるらしいです。

  • クラス制約をする多重定義型の例
    • Hugs> :type (1,[2,3],[4,5,6],7)
    • (1,[2,3],[4,5,6],7) :: (Num a, Num b, Num c, Num d) => (d,[c],[b],a)

第3章の代表例のようなものですね。

--無限のリストを作成するhaskellプログラム
myadd :: Int -> ( Int -> Int)
myadd x y = x + y

unlimlist :: Int -> [Int]
unlimlist n = n:(unlimlist (myadd n 1))

terminalがすごいことになりますね。

  • :(コロン)の演算子は「リストの先頭に要素を追加する」
    • Main> 1:[2,3]
    • [1,2,3]

なるほど。

  • ¬(否定演算子)はnotで書く
    • Main> :type not
    • not :: Bool -> Bool

ここ、聞きたかったんです。巻末の付録Bに記載がありましたね。

  • 関数とは
    • 「1つの引数の型をもらって、一つの型を返す」のが関数の定義です。
    • 途中で引数を一つとった内部的な関数が生成されている。
    • myadd x y = x + yを考えると、((myadd x) y)というイメージ
      • (myadd x)は一つの引数を取る関数であるため、yを引数として取る。

-letはhugsでは使えない>

*1:講義の中でも出ましたが、議事録を次回の読書会の前に読み返すと、意味がよく理解できるようになっているのに気づきました。

静岡Developers勉強会 Haskell読書会に参加しました。

静岡にて初ITコミュニティ活動へ参加

本日、2010年1月16日(金)にshizuoka_developer_haskellに参加してきました。静岡に来てから初めてITコミュニティに参加することもあり、わくわくしながら会場へ5分前に到着し、席を確保。Ubuntuを入れている方もいたりと、流石、IT系のイベントとワクワクしていました!

静岡Developers勉強会 開始前

参加メンバー

今回の参加者は13名。三島、浜松、と馴染みのある土地から来た方、東京という遠方からいらっしゃった方もいました。驚いたことに、今回は、16才の高校生も参加していました。自分でCentOSサーバー組んで、ドメインも取得しているとのこと。素晴らしい!*1

Haskell書けます」って言いたい!

本物のプログラマはHaskellを使う | 日経 xTECH(クロステック)にもありますが、「本物のプログラマHaskellを使う」そうです。「Haskell書けます!」って言えるようになるために勉強するんですね、分かります。というのは冗談で、あまり馴染みのない関数型言語について理解を深めて、今後の業務に活かすのが目的です。

講義の進行について

講義は下記の書籍を担当者がスライドを使って説明し、巻末の練習問題を解く形式で進められました。

プログラミングHaskell

プログラミングHaskell

書籍を用いて、やじゅさんが第1章、第2章を担当し、講義を行ってくださいました。

講義中
小ネタも仕込まれて笑いをさそいつつ、分かりやすい説明でした。ありがとうございました。

講義メモとコメント

発表のスライドはまた別の手段で公開してくださると思うので、今日の講義で私が取ったメモとそれに対するコメントを残しておきます。

  • double(double 2)
    • 「内側のdoubleを適用する方法」と「外側のdoubleを適用する方法」がある
      • 内側のdoubleを先にするのがjava
    • 外側のdoubleを適用すると、計算上、2工程多く必要になる
      • 遅延評価はこちらの方法がよく、Haskellはこちらを採用

遅延評価とは、必要になった段階で計算することです。このため、Haskellでは、無限のリストも評価をしない限り計算可能なので無限のリストも扱うことができるます。

  • 純粋型関数
    • 純粋とは副作用がないこと。参照透過性のおかげで保守性が高い。
  • 再代入(破壊的代入)は許されない
    • ex. a = a + 1
      • i.e. a = 1の後にa = 2 は不可*2

ちなみ、副作用とは次のように言い換えられるようです。

副作用(side effect)というのは、メッセージの表示や、変数への代入といった、状態が変化する作用のことを言うんだ。

http://www41.atwiki.jp/knenethaskell/pages/22.html

http://www.codelogy.org/archives/2007/07/haskell_1_1.htmlやその続編記事によると、HaskellにもIO制御という副作用があるが、それを見えなく(無視する)ように抽象化しているようです。*3

また、参照透過性とは、次のように定義されています。

  1. 同じ条件を与えれば必ず同じ結果が得られる
  2. 他のいかなる機能の結果にも影響を与えない
http://ja.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%29

Haskellでは、「関数が一度決まると値は一意に決まる」のがHaskellの特徴です。しかし、

  • 変数はない?
    • 局所的変数はある。

上記と矛盾するようですが、第6回 局所的な「状態」を利用するためのStateモナド | 日経 xTECH(クロステック)によると、局所的変数を実装するためにモナドを使っているそうです。*4

  • SQLも問い合わせ言語

SQLが分かると、他の問合せ言語が分かります。素晴らしい。

  • 関数ごとに並列演算ができる(i.e. マルチCPUを積んでいる現在の計算機のトレンドに合っている。)
  • 今後は並列化プログラミングが重要(cf. CPUの並列化)
    • Map
      • 与えられたリストを別のリストに変換。入力はリスト。出力もリスト。
  • Reduce関数
    • 入力は関数、値、リスト。出力は値。

並列演算が出来るのもHaskellの特徴だそうです。

  • Tac関数(たらい回し関数)を書くことができる。

Haskellは相当速いらしいです。(cf. 404 Blog Not Found:たらいを回すならHaskell)

  • length関数
    • リストの要素数を返す関数

例えば、「リストの中身が0で割っていてエラーを吐く」場合、リストの長さを計算する際、javaの場合は中のリストを計算しエラーを出力するが、Haskellではリストの中身は遅延評価なので、要素数は計算してくれます。

  • 型推論はある
    • 基本は型推論をしてくれるけど、空気読まないとエラーを吐く
    • ちゃんと型宣言しておくと、意図通りに組まないと絶対に動かない

「引数」「戻り値」「関数」の型を決めましょう。意図通りの動作をしてくれるはずです。

  • Haskellの妙技
    • リストが空になった時点で再起再帰が止まる
  • 単位元は加法は0。乗法は1。

「何をさせるか」に注目しているのがHaskell再起再帰させることが本質ならHakell。

  • Dr.Erik Meijer
    • Microsoftのコンピュータサイエンティスト

C9 Lectures | Tags | Channel 9Haskellの講義の映像を公開しています。

  • !
    • エクスクラメーションマーク
  • !!
    • ダブルエクスクラメーションマーク
    • dx(笑)

確かに、数学系の人がいたら、どつかれましたね。

  • :edit filename
    • filenameを標準エディタで編集する。
  • :reload
    • 現在のファイルを再読み込み
  • :type expr
    • expr の型を表示する

editで編集してreloadするやり方もありですね。

  • リストの要素は全て同じ型でないとダメ

うっす。

  • 命名規則
    • 新しく関数名を定義する場合、キャメル方式(Haskell)先頭が小文字*5
    • ファイル名は特に命名規則はない。
    • 引数がリストの場合、名前の最後にsを付け、複数の値を表現することを示す慣習がある。
      • ns:数値のリスト
      • xs:任意の値のリスト
      • css:文字のリストのリスト

xsがリストを意味するとわからなくて、最初は手間取りました。

  • 演習問題1
    • 問1
      • 計算順序を考えるという問題。問題文の意味がわからん。
    • 問2
      • 証明問題。
    • 問3
      • Haskellのコードを書きましょう。
    • 問4
      • できてないよできたよ
    • 問5
      • できてないよできたよ
  • 演習問題2
    • 問1
      • 問題なし
    • 問2
      • 階乗の定義が楽すぎる。素晴らしい。
    • 問3
      • 小文字、バッククオート、インデント
    • 問4
      • 出来たよ
    • 問5
      • できてないよ

訳者のwebサイトはプログラミングHaskell、著者のwebサイトはPage Redirection。解答も著者のwebサイトにあります。

  • ~は「ニョロ」じゃなくて「チルダ」だよ。

ニョロって呼んでました(笑)気をつけます。

2次会について

初回なので大人しめに参加させてもらいました。ただ、皆さん、開発に関わっている方は、知識が豊富でした。私も負けていられないので、次回は語れる話題を用意しなければ!

今後について

予算が余っていれば課題図書を一冊予備として買う案も賛成です。新規参加者の方も来やすいですし、もし参加し忘れてしまった人も、遅れずについていけますしね。次回は2010年2月27日(土) 13:00に第3章をたかはしさんが発表です。乗り遅れずに頑張ります。
個人的には、「rubyによるwebアプリケーション開発したよ」「興味のある論文を実装したよ」なんかやりたいですが、これは、また別の機会に。

オマケ

おやつ美味かったです。


おやつタイム

*1:私も見習わなければ。

*2:a=1に縛られるということ。

*3:現時点の調査はここまでとします。

*4:こちらも、今後の勉強会に期待。

*5:パスカル方式は先頭が大文字

emacs読み込み専用モードを解除する方法

emacs が起動したら最初から読み込みモードになっている。

これから、勉強会に参加するのにエディタが使えないなんて困る!ということで、http://www.bookshelf.jp/soft/meadow_13.htmlより解除方法を拝借。

読み込み専用を解除するには,モードラインにある「%%」を左クリックするか, C-x C-q や M-x toggle-read-only を利用します.

とのこと。%%をクリックして無事解除。

Ruby技術者認定試験(Silver)に合格して分かったこと 〜脳をインタプリタとして動作させる〜

まずは結果から

2010年1月15日(金)にRuby技術者認定試験(Ruby Association Certified Ruby Programmer Silver)に合格しました。
Ruby技術者認定試験(Silver)
試験時間は90分ありますが、約40分で全50問回答完了しました。82点*1と大手を振って言える点数ではないですが、それでも、頑張った自分へのご褒美のために報告です。

出題内容について

id:nobyuさんのhttp://d.hatena.ne.jp/nobyu/20090724/1248442523が大変良くまとまっています。勉強法や出題傾向については、記事に書いてあるとおりです。助かりました。

試験を通じて習得できるスキル

RubyにおけるStringクラス、Arrayクラス、Hashクラスのメソッドに明るくなります。*2例えば次のようなStringクラスのchopメソッドとchompメソッドの違い等です。

# chopは文字列の末尾の1文字を取り除く。ただし、末尾が"\r\n"の場合は2文字取り除く。
p "hogehoge\r\n".chop.chop # => "hogehog"
# chompは文字列の末尾から行区切りのみを取り除く。
p "hogehoge\r\n".chomp     # => "hogehoge"
# メソッドチェーン
p "hogehoge\r\n".chop.chop.chomp # => "hogehog"

ちなみに、"\r"を「キャリッジリターン(復帰。CR。)*3、"\n"を「ラインフィード(改行。LF。)*4と呼ぶ。

試験勉強方法

id:nobyuさんや同試験に合格した大学時代の同期に倣い、私も次の書籍を購入して試験に備えました。

RUBY技術者認定試験 公式ガイド (ITpro BOOKs)

RUBY技術者認定試験 公式ガイド (ITpro BOOKs)

この書籍を使った勉強法は次のとおりです。

  1. 巻末の模擬試験を解く。
  2. 正解した問題も間違えた問題も解答を読む。
  3. 問題毎に、ノートへ、クラスやメソッドの概要をまとめる。
  4. irbで問題文のコードや自分で考えたコードを実行し、動作を確かめる。
  5. 書籍で分からない内容(ex. メソッド等)が出たら、プログラミング言語 Ruby リファレンスマニュアルhttp://www.namaraii.com/rubytips/を読む。
  6. やっぱりirbで動作を確かめる。
  7. 再度、模擬問題を解き直し、コードの意味を口ずさめるようにする。

インタプリタとしての脳

今回の試験を通じて、プログラミングの習得で必要だと思ったことを列挙すると次の3つになります。

  1. ノートにクラス名、メソッド名、挙動をまとめましょう
    • ノートにまとめることで、コードを解釈し、理解が深まります。
  2. 疑問に思ったら、コードを書くのを面倒くさがらずに、irbを使って挙動を確認しましょう。
    • オブジェクトのclass、破壊的メソッド、引数の違いに起因する挙動の差異
  3. コードを頭の中で解釈して「こう動作するだろう」という試行が出来るようになって初めて「理解した」と言えます

これまでも、「はじめてのRuby」を上記の勉強法を使って習得していました。

初めてのRuby

初めてのRuby

ただ、いかんせん、「例題」はあっても「問題」がないことが私の中ではネックになっていました。*5そのため、今回の試験は良い頭の切り替えになりました。新しい視点で「はじめてのRuby」を読むことができます。

今後について

次は同じ言語でも、「英語」。2010年3月14日(日)にTOEICを受験します。スコアの目標は730点ですが、こちらも「英語のインタプリタを脳に定着させること」を第一の目標に頑張ります。*6

*1:合格点+7点。

*2:意外と正規表現は出題が少ないです。

*3:「カーソルを行の先頭に戻す」の意。

*4:「カーソルを次の行の同位置へ移動する」の意。

*5:昔から、問題を解いて覚えるタイプだった。

*6:実力がつけば、スコアは自然と後からついてきます。