勉強会
無限次元アーベル??
立方体の展開図
ポイントフリーでフィボナッチ?
fib 0 = 1 fib 1 = 1 fib n = (fib (n - 1)) + (fib (n - 2))
fib_ n x y = if (n == 0) then x else fib_ (n - 1) y (x + y) fib2 n = fib_ n 0 1 main = print $ map fib2 [1..10]
fib_ x y n = if (n == 0) then x else fib_ y (x + y) (n - 1) fib2 n = fib_ 0 1 n main = print $ map fib2 [1..10]
Preludeを読む。おー、IやKやTコンビネータがあるね。でも\x, f -> (f x)x的なものはなさそうだ。まずはnを2個に増やさないといけない。これをポイントフリーで作る必要があるな。\f, x -> (f x)xのほうがいいな。
3辺が8センチ、5センチ、3センチの三角形があります。面積はいくらでしょう。
微積分を使わずに円錐の面積を求めるにはどうしたらいいか。
Preludeを読む。お、take 3 $ repeat 2で[2, 2, 2]になるんだ。これにfold系を使えば(f x)xを作れるよなたぶん。
adder x y = x + y main = print $ foldl1 adder $ take 2 $ repeat 2 -- => 4
お、できたできた。
adder x y = x + y foo f = (foldl1 f).(take 2).repeat main = print $ foo adder 2
いけた。次はこのfoo fからfを取り除けばいいんだな。
Prelude> (.(1 +)) (1 +) 2 4
ふむふむ。これを参考にした:ポイントフリースタイル - val it : α → α = fun
foo = (.(take 2).repeat).foldl1 main = print $ foo adder 2
OKOK
foo = (.(take 2).repeat).foldl1 main = print $ foo fib_ 5 0 1
あー、ダメだ。Int->Int->Intじゃないとダメだ。実物はfib_ :: Int->Int->Int->Int->IntだからInt->Int->IntとIntがミスマッチと怒られる。foo f xがT->T->Tだということを、より正確に言うならTをfに2個入れたらTが返ってくることをfoldlが要求してしまう。うむ、そうか。
fib_ :: Int -> Int -> Int -> Int -> Int fib_ x y n1 n2 = if (n1 == 0) then x else fib_ y (x + y) (n2 - 1) (n2 - 1) -- foo f x = (f x) x foo = (.(take 2).repeat).foldl1 main = print $ map (foo (fib_ 0 1) ) [1..7] --[1,1,2,3,5,8,13]
できたできた。
if文はpartionにできないか、さすがに。
cond x y z = if x then y else z fib_ :: Int -> Int -> Int -> Int -> Int fib_ x y n1 n2 = (cond (n1 == 0) x (foo (fib_ y (x + y)) (n2 - 1)))
fib_ x y n1 = ( (.(foo (f2 x y).(subtract 1))) (flip f1 x n1) ) fib_ x y n1 = ( (.(foo (f2 x y).(subtract 1))) .(flip f1 x) ) n1
OKOK だんだんコツを理解してきた
fib_ x y = ( (.(foo (f2 x y).(subtract 1))).(flip f1 x) )
n1が消せた。さて、これをどうするか。
fib_ x y = ( (.) (. ( ((.) (. (subtract 1)) ((foo . (f2 x)))) y ) ) (flip f1 x) )
むむ。(. f(x))なんていう右項だけ埋めるpartionから変数をくくりだすのってどうやるんだろう
Prelude> (.((+) 2)) (* 5) 10 60
これの2をくくりだすんだよな。んー。あ、そうか。
.xは\x, y -> y.xなわけだからつまり\x, y -> (.) y xで、ここでflipが登場して \x, y -> flip (.) x yになって、でyが消える、と。
Prelude> ((flip (.)) ((+) 2)) (* 5) 10 60
OK
fib_ x y = ( (.) ( (.) (flip (.)) ( ((.) (. (subtract 1)) ((foo . (f2 x)))) ) y ) (flip f1 x) )
テスト通った!
fib_ x = flip ((.) (.) ( (.) (flip (.)) ( ((.) (. (subtract 1)) ((foo . (f2 x)))) ) ) ) (flip f1 x)
やったー、yが消えたー
さて、先に進む前にf2 x y = (fib_ y (x + y))をポイントフリーにしよう。
ふむ、yを増やしたいけどさっきの方法は使えなさそうだからどうしたらいいか。とりあえずyを最後に持ってくるのまでは簡単なんだが。
f2 x y = ((flip fib_).(x +)) y y
もう疲れたからいいや。
dup f x = f x x f2 x = dup ((flip fib_).(x +))
えーと
f2 x = (dup ( (.) (flip fib_) (x +) ) )
f2 x = (dup ( ( (.) (flip fib_) .(+) ) x ) ) f2 = (dup.(((.) (flip fib_).(+))))
できたー
fib_ x = flip ((.)(.) ( (.)(flip (.)) ( ( (.)(. (subtract 1)) ((foo . (f2 x))) ) ) ) ) (flip f1 x)
そろそろ僕飽きてきた。3分間クッキング風に「完成させたものがこちらに」
fib_ = dup ( (flip(flip.(((.)(.).((((.)(flip (.))).((((.)(. (subtract 1))).((((.)foo).f2)))))))))).(flip f1) )
完成版の全体のコード
cond x y z = if x then y else z dup f x = f x x fib_ = dup ((flip(flip.(((.)(.).((((.)(flip (.))).((((.)(. (subtract 1))).((((.)dup).((dup.(((.) (flip fib_).(+))))))))))))))).(flip (cond . (0 ==)))) fib = (dup (fib_ 0 1)) main = print $ map fib [1..7]