第5回 スタートHaskell

12/5 に、第5回 スタートHaskell に行ってきました!

会社の先輩 (@seizans) に誘われて、久しぶりの勉強会 & 初スタートHaskell

  • 前日

本の中身をざっくりみた後、演習をやっておこうとした。
環境をみてみると、Haskell Platform 入れてなくて、
Mac Ports の ghc が入っていたので、
そっちはアンインストールして、Haskell Platform を入れようとしたが、
家のネットが調子悪く、とりあえす今回はこのままで行くことに。


割と夜遅くなったので、練習問題と関係ありそうな演習はなんとか終わらせて寝た。

  • 当日

品川駅で迷ったり、大森駅で逆方向から出て迷ったりしたけど、なんとか辿り着けた。


togetter - スタートHaskell第5回 まとめ : http://togetter.com/li/222626

@ruicc さん
資料 : http://www.slideshare.net/RuiccRail/programming-haskell-chapter10


Haskell といえば・・・
モナド?いいえ、型クラスです。

OO: クラス (型)、インスタンス(値)
Haskell: 型クラス(型)、型(型)


型クラスにメソッドがあり、型にフィールドがある、的な。

    • データ構造比較

OO: 直積構造、状態
Haskell: 直積構造、直和構造、再帰構造

data Hoge a (ここまで型の世界) = (ここから値の世界) MkInt Int | MkA a

add :: Int -> Int -> Int (型の世界)
add a b = a + b (値の世界)
    • OOで直和クラス

State Pattern, 状態をフラグ管理 など (大変・・・(特に使う側))
「「状態」と書いて、大いなるバグの母と読む」
OOで再帰構造
Composite, Visitor Pattern (大変・・・)


パターンの粒度が大きく、組み合わせが面倒
意図がばらける
オブジェクトをまたぐ処理が苦手

    • private がない

(Python にも JS にもない)
Haskell だったら
フィールドのprivate
 ロジックを書くのに状態は必要ない (直和で十分)
  パフォーマンスの際には、module単位で隠蔽
メソッドのprivate
 module, where で隠蔽

    • 抽象力比較

OO:
型の継承 - メソッドの依存関係の継承 (フィールド非依存)
オーバーライドが複数回あり得る
実装の継承 - フィールド依存


Haskell:
型クラス間で継承 (多重継承可)
型での実装(オーバーライド)は1回


型クラス - OO のインタフェース的な
型 - OO のクラス (-α) 的な


型クラスのクラスは、集合論のクラスに近いらしい。
同じ性質を持った型の集合。


型クラスの継承

class (親 a) => 子 a where ...
class (親1 a, 親2 a) => 子 a where ...

型クラスにデフォルト実装も書ける
Scala の trait 的な

既にある型に、後から型クラスをつけることも出来る


型での実装

instance 型クラス 型 where ...
data 型名 = ... deriving(型クラス)

で、インスタンスを書くことなく型クラスを実装できる。
(特殊な場合のみ)


種については省略
(* -> * とからしい。まだよくわからん)


仮想マシンの eval と exec (相互再帰)
 左を評価して、右は後で
 後でやるのはスタックに積んでおく


型クラスとOOの話でおおいに盛り上がっていた
(1時間超過)


会場のコンセントに、MBAの電源がささらない・・・
(でかい部分が入らない)

  • 第11章:切符番号遊び

@dekosuke さん


Twitter の数字遊び (10になったー)
 使える演算とかは割と曖昧
切符番号遊び
 四則演算のみ、並べ替え可


テキストに沿った解説


choices は、Data.List の中の関数を使えば、

Prelude Data.List> let choices = (>>= permutations) . subsequences

Prelude Data.List> choices  [1..3]
[[],[1],[2],[1,2],[2,1],[3],[1,3],[3,1],[2,3],[3,2],[1,2,3],[2,1,3],[3,2,1],[2,3,1],[3,1,2],[1,3,2]]

こんな感じで書けた。

@kazu_yamamoto さん
資料 : http://mew.org/~kazu/material/2011-monad.pdf

モナドトップダウンで理解するのは難しい
(とても抽象的)
まずは具体例から見ていくとよい


統一理論と大統一理論
物理
電磁気力 + 弱い力: 電弱統一理論
強い力 + 電弱統一理論 : 大統一理論
あと重力 (アインシュタイン大統一理論とくっつけようとして死んでしまったらしい)


いきなり大統一理論を与えられても分からない
(4つの力があって、それを統一的に扱いたいということが分からない)


モナドも同じ

Haskell
Parser + IO : 状態系
List + Maybe : 失敗系
状態系 + 失敗系 : コンテナ


状態系統一理論
Parser と IO : なんか似ている
共通点 : データ定義、生成する関数、合成する関数


型クラスで共通化
糖衣構文(do)を用意

  • > 命令型言語の逐次実行の再発明!


失敗系統一理論
Maybe は失敗と1つの成功 (答えが0個か1個)
List は失敗と複数の成功 (答えが0個以上)


Maybe は合成できた。
List も出来る!

Maybe の合成は0と1のかけ算っぽい (Nothing が 0)
List もかけ算 (組み合わせ) にする


大統一理論
失敗系と状態系の統一 (Philip Wadler)


コンテナ
中身が一つの型、生成関数、合成関数を持つ
文脈として使える
Parser : パーサー、IO : 副作用表現
Maybe : 失敗しうる計算、List : 答えが0個以上の計算 (非決定性を持つ計算)


文脈が混ざらないこと!


力が弱いものから使う
弱いものほど安全


再帰 > 畳み込み > 単純な高階関数
プログラム可能コンテナ (>>=) > 逐次コンテナ (<*>, return) > マップ可能コンテナ (<$>)

(<$>) :: (a -> b) -> (m a -> m b) (fmap)

f :: a -> b とすれば、

(f <$>) :: (m a -> m b)

f という関数を m という文脈に持ち上げる (lift)


2引数関数 f :: a -> b -> c を、<$> で m の文脈に持ち上げると、

(f <$>) :: m a -> m (b -> c)

関数が文脈 m の中に入る
このような、文脈の中の関数も適用できるようにしたい

(<*>) :: m (a -> b) -> m a -> m b (app)

文脈 m の中の関数を適用している
(逐次らしい)


例えば、

(+) <$> [1,2] <*> [3,4] 

のように書け、
<$> と <*> を消すと、通常の関数適用のように見える

(>>=) :: m a -> (a -> m b) -> m b (bind)

(分岐らしい)


プログラム可能コンテナ : Monad
逐次コンテナ : Applicativce
マップ可能コンテナ : Functor


モナドは、様々なパラダイム(文脈)を統一された形で扱うためのもの


IO は IO。ただモナドとしてあるだけで、
モナドの代表としてIOがある訳ではない
モナドはただの型クラス (Haskell では)
糖衣構文 do がモナドを特殊にしている


リスト内包表記は do 記法の別表現
(現在はリストのみ)


Maybe は >>= で書くことが多いらしい
リストは内包表記で
パーサーは <$>, <*> で
do 使うのは IO くらいらしい


歴史的経緯により、Monad <|- Applicativce <|- Functor とはなっていない


Q: 「マップ可能コンテナで出来ることは?」
A: 「map map map いえーい」


型構築子も関数なので、例えば

data KV = MkKV String Int

とすると、

MkKV :: String -> Int -> KV

なので、

MkKV <$> ["a", "b"] <*> [1, 2]

とか出来る

  • 練習問題

10.3 と TreeMap
問題自体はそんなに難しくなかったが、
Tree の定義を間違えていて、instance の種が合わないとか言われて
しばらく悩んでいた。
やっぱ種周りも知っておきたい。

  • 懇親会

ビールがおいしい店!
炭酸的な感じがないビール。


Haskell の話とか OO の話とか、お仕事の話とか会社の話とか。