第5回 スタートHaskell
12/5 に、第5回 スタートHaskell に行ってきました!
会社の先輩 (@seizans) に誘われて、久しぶりの勉強会 & 初スタートHaskell!
- 前日
本の中身をざっくりみた後、演習をやっておこうとした。
環境をみてみると、Haskell Platform 入れてなくて、
Mac Ports の ghc が入っていたので、
そっちはアンインストールして、Haskell Platform を入れようとしたが、
家のネットが調子悪く、とりあえす今回はこのままで行くことに。
割と夜遅くなったので、練習問題と関係ありそうな演習はなんとか終わらせて寝た。
- 当日
品川駅で迷ったり、大森駅で逆方向から出て迷ったりしたけど、なんとか辿り着けた。
togetter - スタートHaskell第5回 まとめ : http://togetter.com/li/222626
- 第10章:クラスとインスタンスの宣言
@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 の話とか、お仕事の話とか会社の話とか。