大半のGPLの利用者は、勝手にGPLにしたのであって、FSFと契約してGNU softwareにしたわけじゃない。
FSFと契約すれば安全ですってのは何の反論にもなってない。
裁判すればいいというのは、無責任な意見に聞こえる。GPLが契約かただの宣言かということすら確立されてないのに、「契約だとした上で、GPLのspiritまで都合良く理解してくれる」ことを裁判所に期待できるんだろうか。私は法律の専門家じゃないからなんともわからないけれども。*1

*1:シュリンクラップ契約」は法律家の「多く」が有効な契約と考えていないらしいし、素人である私には難しい。(利害関係の無い)専門家が絶対の自信を持って「勝てる」というなら、個人としては、勝てるから心配無いと判断するだろう。

今日は雪だった。ここでは、少しでも積もるのは年に数回しかない。川縁を歩いて下っていると、散歩中の犬に出会った。耳の垂れた、白っぽい毛の犬だった。尻尾を振ってうれしそうに走り回りながら、雪の中に鼻を突っ込んでいた。私はもちろん走り回らなかったし、鼻も突っ込まなかったが、白くなった景色と雪をふむ音を楽しんでいた。
雪を面白がるとはなかなか高度な知性を持っているものである。年に数回しか雪は積もらないのだから、30年生きた人間でも、積もった雪をみられたのは高々90回程度である。犬は十数年しか生きない。そう年おいてもみえないその犬は、今までに何度雪景色を走りまわったろうか。
数人の中学生が歩いていた。一人が雪を取って投げる。二度目には一人が傘で打ち返そうとした。アッパースイングに雪はくだけて飛び散った。
再び犬に出会った。柴犬の彼は平然と散歩し、雪など眼中に無いようだった。

Re:http://www.sampou.org/cgi-bin/haskell.cgi?HowTo%3aQuickCheck&l=jp

接頭辞 prop_ には何の意味もない。適当な名前 (i_want_to_check x = ... ) でもよい。ただし、引数が最低一つは必要で、かつ、引数の型を "types" という関数で教える必要がある(テストできる型に型推論できる場合はその必要はないが、しかしテストできる型が何かなんて最初は知らないので...)。

"types"という関数にも何の意味もないです。型を一つに決めないと、どの型のTestableのインスタンスとしてランダムデータを生成すればいいのかわからない、というだけのことなので、型宣言でもかまいません。

prop_head :: Int -> Bool
prop_head x = x == head [x]

再犯者率に関する反論への反論



私のblogを見ていてhttp://sheepman.parfait.ne.jp/さんを見ていないひとが居られるのかどうか甚だ疑問ではありますが: sheepmanさんからhttp://d.hatena.ne.jp/yts/20050120への反論を頂きました。



書き換えないつもりでしたが、寿命を終えたと思うので、対象読者を変えます。

0

この式の左辺は rna さんのコストパフォーマンスの定義_と同一です。よって、rna さんに対する僕の議論がそのまま当てはまってしまいます。というか、yts さんの上の式の議論は rna さんのそれを犯罪対策の効用を導入するという別の形で繰り返しているだけです。

言葉の(コストパフォーマンスの)定義を合わせないと議論になりません。
コストパフォーマンスの定義を合わせたからこそ、sheepmanさん(や再犯者率が重要だというその他)の議論が当を得てないと論じることができたのです。

1

犯罪 a に関して上の不等式が成立するなら、それは効用がコストを上回っているわけですから、犯罪 b に関係なくミーガン法を導入するべきだということになります。

二つの点で誤っています。

まず第一に、「二つの犯罪のうちどちらかにミーガン法を導入するとする」という、文脈および

次の不等式が成り立つとき、ミーガン法はbよりもaに適用すべきである。
http://d.hatena.ne.jp/yts/20050120#p1

から当然読み取られるものとと私が期待していた前提を無視しています。

第二に、こちらが重要ですが、論理的に誤っています。二つの対策を同時に行ったときには、コストや効用は単に足し算か何かで決まるわけではありません。

例えば、仕事をするのは効用(金銭等)がコスト(時間その他)を上回るからですが、
sheepmanさんの議論に従う人:
「仕事Aか、これぐらいの給料ならいい。ふむ、仕事Bはもっといい。Cはぎりぎりプラスかな。まず、仕事Aの効用は正だから、BやCにかかわりなく、やるべきだ。Bもそうだ。Cもそうだ。よし、全部効用はプラスだから、AもBもCもやろう。一日23時間労働だが効用はプラスだ!」
私が述べた事
「仕事を二つから選ぶとしたら、より効用の高いものを選ぶのが良い」

1.1

この問題点をもう一度指摘しておきます。

最大限投資した(全員に対策した)時の効果を元にコストパフォーマンスを比較してもあまり意味がありません。1円投資して2円回収するほうが、100万使って150万回収するよりいい、といっているようなものです。
http://d.hatena.ne.jp/yts/20050120#p1

2

それに A(t) = B(t) かつ a(t) = b(t) を仮定してしまうと、再犯者率が高い方の犯罪は同時に再犯率の高い犯罪なわけですから、「再犯率は重要ではない」という結論は出てきません。

同値だから重要でない(再犯率を計算しても意味がない)というのが、私の論の骨子です。定理1はまさにそれを述べているのです。
一方、sheepmanさんの主張は

だから「再犯率」が「再犯者率」より重要になる。
http://sheepman.parfait.ne.jp/20050109.html

ですから、少なくともこの仮定のもとでは、否定されてしまいます。

http://sheepman.parfait.ne.jp/20050110.html では A(t) = B(t)( (C_A = C_B)と書かれている)を仮定されていますが、最初のコストパフォーマンスの比較以外は、計算すればわかりますが、再犯者率でも全く同じ議論が成り立ちます。つまり、「より重要になる」ことを示す目的には無価値です。

唯一残った、コストパフォーマンスの比較はどうかというと:
(上の仕事の選択と同じ様に)全く怪しげな仮定

コストが人数に比例するという仮定もどうかと思います。

の元でしか成立しない話である「上に」、1.1のような疑問まである、という状況にあるわけです。

Continuation Monad (4)

一応最後まで書いておく。でも随分前に書いたのでどう考えたのかは忘れてしまった。

13.4 Coroutines

まずcoroutine macroを定義する。

(define-macro coroutine
  (lambda (x . body)
    `(letrec ((+local-control-state
               (lambda (,x) ,@body))
              (resume
               (lambda (c v)
                 (call/cc
                  (lambda (k)
                    (set! +local-control-state k)
                    (c v))))))
       (lambda (v)
         (+local-control-state v)))))

Haskellはlazyなので、strictなSchemeではマクロでないとできないことが関数でできる。
condやifは簡単だ。しかしこのマクロの場合はそれほど簡単ではない。継続を呼び出すときに使うためのresumeが"+local-control-state"を参照しているためだ。

(define make-matcher-coroutine
  (lambda (tree-cor-1 tree-cor-2)
    (coroutine dont-need-an-init-arg
      (let loop ()
        (let ((leaf1 (resume tree-cor-1 'get-a-leaf))
              (leaf2 (resume tree-cor-2 'get-a-leaf)))
          (if (eqv? leaf1 leaf2)
              (if (null? leaf1) #t (loop))
              #f))))))

上の二つのresumeは、このcontine macroの呼び出しに固有の"+local-control-state"を呼び出す必要がある。
隠れて"+local-control-state"をresumeに渡すためにReaderモナドを使うと、以下のようになる*1

coroutine :: (t -> ReaderT (STRef s (t -> ContT r (ST s) a)) (ContT r (ST s)) a)
             -> ContT r2 (ST s) (t -> ContT r (ST s) a)
coroutine lambody 
  = do  local_control_state <- lift $ fixST (\local_control_state -> 
          newSTRef $ \init_arg -> 
              do  runReaderT (lambody init_arg) local_control_state)
        return $ \init_arg -> 
            do  lcs <- lift $ readSTRef local_control_state
                lcs init_arg
resume :: (a -> ContT r (ST s) c) -> a 
           -> ReaderT (STRef s (c -> ContT r (ST s) b)) (ContT r (ST s)) c
resume c v = 
  do  local_control_state <- ask
      lift $ callCC (\k -> 
        do  lift $ writeSTRef local_control_state k
            c v)

このように、resumeに引数を渡すこととを避けられた。

make_matcher_coroutine tree_cor_1 tree_cor_2
    = do  coroutine $ \_ -> 
            fix (\loop -> 
              do  leaf1 <- resume tree_cor_1 (error "get_a_leaf")
                  leaf2 <- resume tree_cor_2 (error "get_a_leaf")
                  if leaf1 == leaf2 then
                      if  isNull leaf1 then return True else loop
                    else return False)
(define make-leaf-gen-coroutine
  (lambda (tree matcher-cor)
    (coroutine dont-need-an-init-arg
      (let loop ((tree tree))
        (cond ((null? tree) 'skip)
              ((pair? tree)
               (loop (car tree))
               (loop (cdr tree)))
              (else
               (resume matcher-cor tree))))
      (resume matcher-cor '()))))
make_leaf_gen_coroutine tree matcher_cor
    = do  coroutine $ \_ ->
            do  fix (\loop tree ->
                  do  cond [(isNull tree, return (error "skip"))
                          , (isPair tree, loop (car tree) >> loop (cdr tree))
                          , (otherwise  , resume matcher_cor tree >> return (error "next"))]) tree
                resume matcher_cor (Tree []) 
                fail "impossible"

次はsame-fringe?だ。
ここでletrecをこう定義してみる。この定義は、中でrunContTを実行しているので、継続を保存しない。つまり、letrecの中でcall/ccを呼んだりする使いかたに対しては正常に(schemeで期待されるように)動作しない。しかし、一般的な使用では問題がない。

letrec f = lift $ mfix $ \x -> runContT (f x) return

Unfortunately, Scheme's letrec can resolve mutually recursive references amongst the lexical variables it introduces only if such variable references are wrapped inside a lambda. And so we write:

とあって、Schemeでも matcher-cor を lambda (v) (matcher-cor v) と書いて名前解決を遅らせなければならないように、ここでreferenceを挟むか、runContTしておかないと、無限ループになる。ここではletrecの中でrunContTを走らせてしまうことにした。

(define same-fringe?
  (lambda (tree1 tree2)
    (letrec ((tree-cor-1
              (make-leaf-gen-coroutine
               tree1
               (lambda (v) (matcher-cor v))))
             (tree-cor-2
              (make-leaf-gen-coroutine
               tree2
               (lambda (v) (matcher-cor v))))
             (matcher-cor
              (make-matcher-coroutine
               (lambda (v) (tree-cor-1 v))
               (lambda (v) (tree-cor-2 v)))))
      (matcher-cor 'start-ball-rolling))))
same_fringe' tree1 tree2
    = do  (_, _, matcher_cor) <- letrec (\ ~(tree_cor_1, tree_cor_2, matcher_cor) ->
            do  t1 <- make_leaf_gen_coroutine tree1 matcher_cor
                t2 <- make_leaf_gen_coroutine tree2 matcher_cor
                mc <- make_matcher_coroutine tree_cor_1 tree_cor_2
                return (t1, t2, mc ))
          matcher_cor (error "start-ball-rolling")

テスト

d01 = Tree [Leaf 1, Leaf 2, Leaf 3]
d02 = Tree [Leaf 1, Tree [Leaf 3, Leaf 2]]

f10 = runST (flip runContT return $ same_fringe' d01 d02)
f11 = runST (flip runContT return $ same_fringe' d01 d01)

>

*1:implicit paramterでも良い