(高校で習うはずの)数学的帰納法をはじめとする帰納法(induction)と、(π計算など並行プロセス計算に出てくる)双模倣(bisimulation)をはじめとする余帰納法(coinduction)は、双対(dual)であると言われます(例)。双対というのは、大雑把に言うと、論理式のド・モルガンの法則 ¬(A∨B) ⇔ ¬A∧¬B と ¬(A∧B) ⇔ ¬A∨¬B のように、何か一組のもの(ここでは∧と∨)をひっくり返しても同じ式が成り立つという関係です(例)。 しかし、自分は学部4年ぐらいのときに余帰納法(というか双模倣)を習って、「(数学的帰納法のような)帰納法と(双模倣のような)余帰納法が双対」と聞いても、何となく「余帰納法は結論を仮定する(?)から、仮定を仮定する(?)帰納法と反対なのかなあ」と思うぐらいで、恥ずかしながら何が双対なのかよくわかりませんでした。かといって、詳しい人
エラトステネスの篩の前に, 階乗をArrowでやります. 理由はおいおい分かります. 階乗を普通に fact n = if n == 0 then 1 else n * fact (n - 1) main = print $ fact 10 3628800 流石にこれはいいですね. はい. Arrowに急ぐ前に, まずfixを使って書きましょう. 色々考えましたが, fixを介してArrowに行くのが一番近道です. fix f = f (fix f) fact = fix fact' fact' f n = if n == 0 then 1 else n * f (n - 1) main = print $ fact 10 3628800 さっきのfactを, 第一引数で関数を回すようにしてやるだけですね. 階乗をArrowLoopで さて, fixで書けたらもうお手の物です. というのも
今日はちょっとコードの効率化の話をいったんお休みして、別の話を書きたいと思います。 以前に書いたControl.Arrow.loopでも実はさりげなく出ていたのですが、Haskellではletとwhere節の部分でちょっと変わったことができます。 Control.Arrow.loopの定義を見てみます: instance ArrowLoop (->) where loop f b = c where (c,d) = f (b,d) ちょっと不思議な関数定義なわけなんですが、特に変わっている部分があります。…それは変数dの宣言部分です。 (c,d) = f (b,d) loopの説明によると、これの影響で変数dは再帰の全ての段にわたって同じインスタンスが参照されているということらしいです。つまり、whereとletでは定義内での変数の再帰的参照が許されているようです。 おかげで、こんなことも
効率化の話はなんだか疲れるので、またデータ再帰の話へ脱線… id:dachs_hippoさんのfixに関する記事をボーっと読み返していてあることに気づきました… 氏のサンプルのひとつは階乗の計算だったわけですが: import Data.Function g :: (Int -> Int) -> Int -> Int g rec 1 = 1 g rec n = n * (rec $ n - 1) main = print $ (fix g) 4 ここに出てくる関数gは無理にfixを使わなくても当然かけるわけです… g :: Int -> Int g 1 = 1 g n = n * (g n - 1) main = print $ g 4 この2つを比較して見えてくることは、fixを使ったほうで出てくるgの第一引数recはほとんど関数g自身の別名のような存在だということです…逆に考えれば、f
リリース、障害情報などのサービスのお知らせ
最新の人気エントリーの配信
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く