プログラマのための圏論勉強会のために予習中。
iOSDC Japan 2018 「圏論とSwiftへの応用」発表スライドメモにある動画やスライド、記事を見ながら、丸と矢印を書いて頭をひねっていました。
発表の途中、「自然変換」までですが、読んでるだけではさっぱり分からない
→動画を見つつ、「みんなもここで???ってなったんだ」と安心して
→手書きでノートに丸と矢印を書きまくって、なんだか理解できたような気がして
→発表資料のswiftのコードをコピって真似してこねくり回して、やっと腑に落ちた
って感じでした。
2018/10/15追記: ここで書いたコード Setを関手としてやっていますが、Setは関手にならないとの指摘をもらいました。なのでコードとしては動くけど間違ったコードになっています。
import Foundation
// 「iOSDC Japan 2018 「圏論とSwiftへの応用」発表スライドメモ」を参考
// https://qiita.com/inamiy/items/3e0c10d5eaf234b41c3d
// 恒等射
func id<A>(_ a:A)->A {
return a
}
// 関数の合成
infix operator ∘
func ∘ <A,B,C>(_ g:@escaping((B) -> C), _ f: @escaping((A) -> B)) -> ((A) -> C) {
return { g(f($0)) }
}
// 関数の合成のお試し
func count(_ s:String)->Int {
return s.count
}
func isEven(_ i:Int)->Bool {
return i%2 == 0
}
let 合成関数 = isEven ∘ count
print( 合成関数("hoge") ) // 4文字だからtrueになる
print( 合成関数("hoge2") ) // 5文字だからfalseになる
print( (count ∘ id)("hoge")) // どっちも4になる
print( (id ∘ count)("hoge")) // = 「結合律」
// 射: StringからInt(文字数カウント)
func f(_ s:String)->Int {
return s.count
}
// 関手F: Arrayで包む
func F<A,B>(_ f:@escaping((A)->B)) -> (Array<A>) -> Array<B> {
return {arr in
arr.map{f($0)}
}
}
// 関手G: Setで包む ※ここ間違っている。 Setは関手にならない。※
func G<A,B>(_ f:@escaping((A)->B)) -> (Set<A>) -> Set<B> {
return {set in
Set(set.map{f($0)})
}
}
// 自然変換alpha: ArrayからSetに変換
func alpha<T>(_ a:Array<T>)->Set<T> {
return Set(a)
}
// (alphaA,alphaBは型を指定しているだけで、なくても行けた)
func alphaA(_ a:Array<String>)->Set<String>{
return alpha(a)
}
func alphaB(_ a:Array<Int>)->Set<Int> {
return alpha(a)
}
print((alphaB ∘ F(f))(["hoge","3","hehehe"])) // 上と下は同じ結果を返しているけど、偶然同じ順番になっているだけ。
print((G(f) ∘ alphaA)(["hoge","3","hehehe"])) //
print(alphaB(F(f)(["hoge","3","hehehe"])))
print(G(f)(alphaA(["hoge","3","hehehe"])))
まだまだ先は長そうです。