やったこと
シャニ
黒セーラの灯織のTrue。
Sランクで親愛Maxなのでいい感じなのでは。
コミュも良かった。
https://twitter.com/make_now_just/status/1355550860583993351
あとフェスイベントを終わらせた。
最近シャニをやる時間がない。
minicheck
色々考えたら思い付いてしまった。
天才かもしれない。
R を乱数生成器として、gA:R→(R×A) を型 A の値を生成する生成器オブジェクトとする。
a∈A について gA(r)=(r′,a) となる r∈R が存在するとき、gA は a を生成可能といってa∈~gA で表す。
このとき任意の a∈A について a∈~gA のとき gA は網羅的である、という。
当然だが、生成器オブジェクトは網羅的であることが望ましい。
cA:∀B. (R→(R×B))→(R→(R×(A→~B))) を A に対するco-生成器オブジェクトとする。
ただし A→~B は A から B への部分関数を表すデータ構造の全体からなる集合とする。
cA と gB があるとき、A から B への関数を生成する生成器オブジェクト g→(cA,gB) を構成できる。
gA について g∗(gA):R→(R×A∗) を A の値の列 (リスト) を生成する生成器オブジェクト、
cA について c∗(cA):∀B. (R→(R×B))→(R→(R×(A∗→~B))) を A の値の列に対するco-生成器オブジェクトとする。
gA と cB が与えられたときに、
c→(gA,cB):∀C. (R→(R×C))→(R→(R×((A→B)→~C))) を構成できるだろうか?
考えられる1つの方法として、次のHaskell風の疑似コードで説明されるようなものがある。
c→ (gA,let in cB)(gC)(r0)=(r1,a)=gA(r0)(r2,f1)=g→(cB,gC)(r1)(r2,λ f2↦f1(f2(a)))
つまり、A の値と B→C の関数を生成しておいて、渡ってきた A→B の関数に A の値を、その返り値を B→C の関数に渡すことで、最終的に C の返している。
これは一見上手く動作しそうだが、実際には網羅的ではないという問題がある。
具体的には、この方法では A×CB 種類の値しか生成できないが、 (A→B)→C の値の種類は CBA 程度あるので、必然的に漏れが存在することになるわけである。
ここで1つの事実を確認する。
B∗ には A→B と同型となる部分が存在する。
つまり A={a1,a2,⋯} とおいたとき、 f:A→B があれば [f(a1),f(a2),⋯] として B∗ の元が得られて、反対に [b1,b2,⋯] があるとき f(ak)=bk として f を構成できる。
よって B∗→C は (A→B)→C よりも真に大きい。
これを利用して、次のような疑似コードで説明する方法を考える。
c→ (gA,let in cB)(gC)(r0)=(r1,s)=g∗(gA)(r0)(r2,f1)=g→(c∗(cB),gC)(r1)(r2,λ f2↦f1(map(f2,s)))
つまり、 A の値の列と B∗→C の関数を生成しておいて、渡ってきた A→B の関数に A の列の各値を適用して、その返り値の列を B∗→C の関数に渡すことで、最終的に C の値を得ている。
この方法ならば、各生成器オブジェクトやco-生成器オブジェクトが網羅的に機能していれば、こちらも網羅的となる。
しかし、列の生成器オブジェクトは重複する値を持つ列を生成する可能性があるが、そのようなものはこの場合では無駄である。
そこで、次の値の重複しない A の列を生成する生成器オブジェクト g≤(gA) を g∗(gA) の代わりに用いれば良いのではないかと思われる。
g≤(gA) =f([])where f(s)(r0)if a∈s=let (r1,a)=gA(r0) in then s else f(s⋅[a])(r1)
というのが今のところの考察となる。
かなり良く考えられているのではないかと思う。
単一の値の代わりに列や集合を渡す、というのはわりと思い付くアイディアかもしれないけれど、それをちゃんと意味付けできたことに意義がある。
が、いくつかあやしいところもあって、例えば「B∗ には A→B と同型となる部分が存在する」というのは A が有限集合じゃない場合かなり嘘っぽい。
まあ無限リストが許されるなら可算集合でもいけると思うけど、非可算な場合はどうすればいいのか検討もつかない。
とはいえ、コンピュータで表現できるデータが非可算になったりするのかもよく分からないので何とも言えない、という感じ。
どうにか昇華した感じがする。楽しいね。