Haskell Day 2018 に来ましたので、自分用のメモを残しておきます。タグは #HaskellDay です。
作りながら学ぶHaskell入門 / @igrep さん
Haskellを導入した話とHRRの紹介 / @khibinoさん
- 2008年 PerlからJavaを呼び出していた
- 検討 => Common Lisp, OCaml, Haskell
- Haskell の unix パッケージが良かった
- 2010年から
- パーサコンビネータ attoparsec のおかげでテキスト処理が書きやすい
- DB2 のパッケージを debian 用に変換するビルドシステム
- STMによる、状態のあるマルチスレッドプログラム
- DSLの定義がしやすい (Monad, HRR)
- ここから HRR の紹介
- SQL を組み立てる Haskell 内 DSL
- 部品化、型安全
- コンパイル時に Database Schema 読み込みが可能
- 2013年から開発開始
- SQL を関係演算的に書く
- リスト内包表記的に書ければよい
- 最近は
#name p == #name b
的な書き方をサポート - 素のHaskellなので、変数に代入して再利用可能
- window 関数などもサポートしている
- Q). パフォーマンスでハマりは?
- A). 認証データを
bytestring
で入れてたら、フラグメンテーション
- A). 認証データを
- Q).
#name
は拡張?- A).
OverloadedRecordFields
拡張
- A).
- Q). 業務で使うには?
- A). 外部コマンド呼び出しとか、そういうところが効く
- Q). esqueleto と比較したHRRの一押しポイント
- A). 試してくださっている方の意見によると、HRRの方が記述力が高い
- A). 「esqueleto は型安全ではないです」
Servantで行う安全かつ高速なAPI開発 / @nakaji-dayo さん
- Haskell を使ってみよう、と思ってもらうのが目標
- WebAPIとBatchの開発にHaskellを利用
- 課金のあるSNS(!!)
- 顧客管理などの社内ツール
- WAFは Servant を利用、 HRR を利用
- Servantは型レベルプログラミング
- 型安全、型による副産物
- HRR / 型が合えば正しいSQL
- 一連の機能の呼び出しが型で守られるようにしたい
:>
エンドポイントの定義をつなぐ、:<|>
でエンドポイント同士をつなぐ- 実装は
Handler
モナドで- 定義と実装が一致する
ExceptT ServantErr IO
IO
と HTTP エラーコードを例外として投げる機能
- API定義から
servant_swager
でSwaggerを生成できる servant-mock
ランダムな値を返すモックサーバReaderT
でHandler
を拡張する (DBプールなど)- 型による制約
MonadService
HTTP例外を投げないMonadView
副作用を起こさない- view でクエリを投げようとすると型エラー
- 型安全なテンプレート
heterocephalus
,shakespeare
- e-mail などに利用
- REPL で
Handler
を呼べるdef
と レンズで巨大なテストデータでも完結に作れる
- 利用ライブラリはたくさんある
- RDBMS: HDBC, HRR
- Elasticsearch: bloodhound
- AWS API: amazonka
- Google API: gogol
- Firebase は網羅的なものはない
- ライブラリの問題点
- 新しいものに対する対応
- マルチバイト文字
- ニッチなもの (和暦、バグったCSVのパーサ)
- まとめ: Haskellすごい
- Q). 開発チームと教育は
- A). 3人、アルバイト、ペアプロ。おすすめ構成、本を。
- Q). バックエンド以外は?
- A). 適材適所。 elm は使ったことはある
並列並行言語Haskell / @syocy さん
- 今日の元ネタ: Haskellによる並列・並行プログラミング
- CPUのトレンド
- シングルスレッド性能が伸び止まり、論理コア数が増えている
- 10以上の物理コアを持つCPUがご家庭でも
- 12 core で $399 、 32 coreで $1,799
- 並列並行言語
- go, Erlang(Elixir), Rust
- Haskell (GHC) の並列並行の歴史は古い
- 1997年頃には決まっていた
- 純粋なコードの分離: 並列性
- 軽量スレッド: 並行
- 並列 parallel = 同時に進めて高速化すること
- 並行 concurrent = 同時に進んでいるように見せる
- 分散 distributed = 複数のマシンを使う、共有メモリがない、障害を仮定
- 並行のほうが簡単
async
で軽量スレッド生成、wait
で待つ、cancel
も可能cancel
すると非同期例外(難しいので略)が飛ぶ
- スレッド間通信
MVar
アクセスの公平性STM
複雑な処理をミスなく書きやすい
atomically
STM のトランザクションを作る- ランタイムによる軽量スレッド、構文の軽さ、STMによる簡潔さ
- 「A Tour of Go in Haskell」 を作ったので見てね
- Haskellはランタイムへ指示しただけでは並列に評価しない
- 並列に評価してほしい場所を
par
pseq
で指定する
- 並列に評価してほしい場所を
- 評価戦略:
using
で評価戦略を指示 - 自動的な並列化
Par
モナド- データフロー並列とパイプライン並列
Haxl
- データソースへのクエリを並列化
- 行列計算での並列化
repa
,accelerate
(GPU)
- 分散プログラミング
distributed-process
- Erlang のモデルに近い
- ThreadScope
- 各スレッドのリソース使用量を可視化する
- 最近の並列・並行関連
- 軽量スレッドの消費メモリ
- TSO.h によると、 1kb + 18word 。1,000個で1MB
- Q).
STM
で公平性がないのはなぜ?- A). 書籍を買いましょう
- Q).
map
を自動で並列化できる?- A). コンテナの実装によって変えられる
Dhall: Haskellの新たなキラーアプリ / @syocy さん
- 設定ファイルとは?
- コンパイルせずにプログラムのパラメータを変えたい
- 設定ファイル言語は機能が不足している
- DRYじゃない、型検査がない、分割したい、無限ループして欲しくない
- Dhall
- 型、関数、インポートの機能
- チューリング完全ではない
- 「ダール」か「ドール」
- 言語仕様があり、参照実装がHaskellで書かれる
- 型
Bool
,Natural
,Integer
,Double
,Text
List
,Optional
,Record
,Union
- インポート
- ローカルパス、URL(ハッシュ値指定でチェック可能)、生text
- Dhall は実用的か
dhall-to-yaml
dhall-to-json
を使えばよい- Kubernetes は大量の YAML
- "Wall of YAML"
dhall-kubernetes
がある
- 型ファイルを作って読み込む
- デフォルト値を作る
^
でレコードを組み合わせる
- ここからは補遺
- Haskell では
dhall
コマンドが便利dhall format
,dhall repl
- 多相関数、カインドもサポートしている
- 型推論はない。型を明示的に適用
- Haskell では直接DhallファイルをHaskellの型として読める
- 事例: 跋扈(ばっこ)する混沌のJSONをDhallで書き換え
- invalid JSON 生成のため、
dhall-to-json
は使えない・・・
- invalid JSON 生成のため、
- Q).
makeYaml
を使ったファイルをdhall-to-json
すると?- A). サポート外
- Q). 言語としてみたときに Dhall の改善点は?
- A). オプショナルとリストの記号が同じなのがちょっと。だったが、そこにだけ型推論が入った
- Q). JSON, YAML を Dhall にするには?
- A). 手動でやるしかない
- Q). http, https を認証が必要な場合は? コンフィグはプライベートのはずなので
- A). 不明。サポートあるかも。
- Q). 外からとってくる理由は?
- A). オフィシャルな型をローカルで使いたかったり
- Q). ビルトイン関数はあるが、関数を作るのは?
- A). Dhall 上で書く関数であれば簡単。ループも書ける
Semigroupとは? Monoidとは? 環とは? / @aiya000 さん
- 代数をHaskellで実装する
- 今日のスライドと標準ライブラリは若干違う
- マグマ : 足し算(あるいは掛け算)ができる
- マグマのインスタンスは型から一意に決まらない
- 足し算と掛け算、など
newtype
で
- 半群:
x <> (y <> z) == (x <> y) <> z
結合法則 - モノイド: 単位元
e
,e <> x = x = x <> e
NonEmpty
First
Last
は単位元がないのでモノイドではない
- 群: 逆元
x ^ (-1)
- 「可換な」「アーベル」
x <> y = y <> x
- unification に使える
- 擬環: 加法群、乗法半群、分配法則
x >< (y <> z) = (x >< y) <> (x >< z)
(x <> y) >< z = (x >< z) <> (y >< z)
- 環: 乗法がモノイド
- 半群の準同型写像
f (x <> y) = f x <> f y
- モノイドとなる
- 群、モノイドも同様
- すべての道はモノイドに通ず
- 体: 乗法が群 (
0
を除く)- 引き算、割り算ができる
- Q). unification とは?
- A). 懇親会で
- Q). 代数的構造は代数とは言わない
- A). 代数は具体的な物を指す。(環状の代数、リー代数)
HaskellでCLI / @matsubara0507 さん
- プログラムを新しく学んだら CLI を作るはず
getArgs
コマンドライン引数。空白区切りSystem.Console.GetOpt
いい感じに型にしてくれるoptparse-applicative
- よりリッチなこと
- 難しい。簡単なラッパー多数
- サブコマンドを定義できるが網羅性がない
extensible
で解決できる- わからなかったらextensible攻略wikiを
Prelude
- Haskell で勝手にインポートされるモジュール
NoImplicitPrelude
プラグマで止められる
Prelude
だめじゃん、ってなる時期が来る- 代替品がたくさんある
rio
stack
開発チームによる alt Prelude- 帯域環境、ログ、
text
,bytestring
,directory
,filepath
,containers
,lens
,time
,vector
- 例: medium
- Haskell Stack
- cabal hell を防げる
stack new
した後はだいたい同じ- GraphQLのクライアント誰か作って
gloss: 動かして遊んで学ぶHaskell / @lotz さん
- Haskell入門後ありがち 「ネタがない」
gloss
- 2Dグラフィックを簡単に描画
- ゲームも作れる
- Twitterで「glossで作ってみた」して欲しい
display
InWindow
text
などanimate
時間を受け取って図形を帰すsimulate
シミュレーション、play
イベントハンドラ
line
線分circle
circleSolid
rectangleWire
rectangleSolid
text
フォント指定、日本語表示はできない- 座標系
- 真ん中が (0, 0)
translate
scale
拡大縮小 x 座標、 y 座標、別rotate
color
- Picture は
Monoid
- 例: 2重振り子のシミュレーション
simulate
関数- 引数
model
model -> Picture
ViewPort -> Float -> model -> model
時間発展させる
- 二重振り子のモデル
- 角度θを2つ
hamilton
- ハミルトン力学
- 物理系からフェーズを進めてくれる
System
,mkSystem'
- デカルト座標と角度の座標系を2つ使う
- 振り子の絵を作る
- 線と丸を適切に組み合わせるだけ
- 例: コモナドで作るライフゲーム
- コモナド
extract
とduplicate
- 周りが 2個か3個であれば生存
- 生存パターン: ブロック、ブリンカー、グライダー
Z [a] a [a]
1つの要素に注目した無限リストleft
right
を定義できるextract
は自明duplicate
は、left
とright
でそれぞれ移した無限リストをもたせる
Z2 (Z (Z a)
extract
は自明duplicate
4方向にずらした無限リストをもたせれば良い
neighbours
周りの個数、life
時間発展させる- コモナドの
extend
で、ライフゲームが完成する - 遅延評価によって、この実装でも動く
- 見える部分だけの評価でいいので
- 計算量がどんどん増える
- トーラス上に実装すれば解決できる?
IO
を使いたければ、simulateIO
PlayIO
- 例: カオスゲーム
- 多角形(三角形)の頂点と適当な点の内分点をどんどん追加するとフラクタルが書ける
- クリックして適当な点を決める
Liszt あるいは永続データ構造を真に永続させる方法 / @fumieval さん
- バイト列のリストに
- 名前をつけて
- 1つのファイルにリアルタイムで
Map [ByteString] ByteString
insert
Transaction
モナド内で追加commitFile
で変更を反映liszt
コマンドでサーバを立てるfetch
で取得Request
でとり方を指定するcommitFile
でファイルを指定し、"hello, world"
を書き込む- Skew binary random access list を要素として持つ 2-3 Tree
- Skew binary random access list
- アップグレード、ダウングレード
- 一部を取り出すのに適したデータ構造
- 純粋関数型構造の本を参照
- リーフ 0 ~ 2枚、または 2ノード、 3ノード
- ルールが複雑だが、値をバランスよく配置できる
- 途中でエラーで落ちてもデータは残る
inotify
で検知できる- extensive 攻略wikiのバックエンドとなっている
- Kafka との比較
- 1つのファイルにアーカイブできる
- パフォーマンスは劣る
- 書き込みにサーバがいらない
- Franz Kafka に対抗して Franz Liszt とした
- GCを実装したい
- データ構造の永続化、圧縮
- Q). 何Gくらいまでいける?
- A). 100GB くらいまでならなんともない
- Q).
acid-state
との違いは?- A). 1個のデータかどうか? 詳しくないので詳細は
- Q). RDBMSっぽくなりますか?
- A). それはないです(即答)
- Q). ローカルファイル以外に保存は?
- A). 書き込みはローカルに限定
- 最後に自己紹介