Applicative、pure、関数についての再考、帰ってきた Functor

引き続き Haskell
前回は↓
関数がファンクターである、とは - doitakaの日記


タネ本は『すごいHaskellたのしく学ぼう!』。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!


ファンクターについて色々まとめてみた勢いで、アプリカティブファンクターについて考えようとしたものの、見ていくうちにやはり自分は分かったようで分かっていなかったのではないか、と悩んでしまったので、色々と考えなおす。

Applicative、pure

Applicative 型クラスの実装。

class Functor f => Applicative f where
    pure :: a -> f a
    (<*>) :: f (a -> b) -> f a -> f b

『すごい』の説明。

pure は任意の型の引数を受け取り、それをアプリカティブ値の中に入れて返します。

<*> は関数の入っているファンクター値と値の入っているファンクター値を引数に取って、1つ目のファンクターの中身である関数を2つ目のファンクターの中身に適用するのです。


説明と例を見れば分かったような気にはなるのだが…というところである。
引き続き、アプリカティブファンクターとしての関数において宣言がどうなるか、 f に r -> を当てはめるとこうなる。

    pure :: a -> (r -> a)
    (<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> b)

実装はこうなる。

instance Applicative ((->) r) where
    pure x = (\_ -> x)
    f <*> g = \x -> f x (g x)


このあたりでお手上げになってくる…。
とりえあず pure の説明を『すごい』から引くと、

ある値を、pure を使ってアプリカティブ値に包んだものは、元の値を生み出せないといけません。つまり、その値を再現できるような最小限のデフォルト文脈でなければなりません。そこで、関数のアプリカティブなインスタンスの実装における pure は、値を取って「引数を無視して常にその値を返す関数」を作るようになっています。

となっている。
「その値を再現できるような最小限のデフォルト文脈」…???
ここまで来て、「文脈」とは何なのかということについて、イメージを明確にできていなかったことが浮き彫りになってきた感がある…。


関数にとってのデフォルトの文脈とは何であるか。Functor では登場しなかったデフォルトの文脈という概念が、なぜ Applicative では登場する必要があったのか。 ……このあたりを再考してみたい。

関数についての再考

まず、関数における pure の動作を確認する。

pure x = (\_ -> x)

なんなんだこれは…というところだが。
『すごい』の例では、

ghci> (pure 3) "blah"
3

となっている。
この時、pure 3 は、型としては [Char] -> Int になっているはずである。


だが、定義から明らかなように、pure で作られた関数は、どのような値にも適用可能である。

Prelude Control.Applicative> (pure 3) 2
3
Prelude Control.Applicative> (pure 3) [1,2,3]
3
Prelude Control.Applicative> (pure 3) ("a", "b", "c")
3


この関数は、ほとんど定数である。
言い換えれば、「何らかの値に適用することで定数になる関数」となる。
そして、もっと言えば、その「定数」は、すなわち、pure の引数となっていた「元の値」である。
ならば、「何らかの値に適用することで元の値になる関数」である。
これは、「ある値を、pure を使ってアプリカティブ値に包んだものは、元の値を生み出せないといけません」という説明の通りとなる。
では、「つまり、その値を再現できるような最小限のデフォルト文脈でなければなりません」と言われている時の、「最小限のデフォルト文脈」とは何なのか。


……と、ここまで書いてきてだが、整理できているようで整理できていないような違和感がある。
「x に pure を適用することで、(pure x) という関数ができる」の時点では、x は目的語的である。
が、「(pure x) を y に適用する」では、(pure x) は動詞的な扱いになる。
そして、「 (pure x) y の結果、 x が得られる」で、また x が目的語に戻っている。
x という要素を中心にして見ようとしても、x の扱いがころころ変わってイメージしづらい。問題はどうも、「関数を値に適用する」という言い方の部分のようである。
つまり……、「関数を値に適用する」という言い方では、関数が動詞のように見えてしまい、「値が関数によって変化した」というニュアンスになる。これに従うと、(pure x) y のケースでは、「(pure x) を y に適用した結果、y が x に変化した」ということになってしまう。これはどうもおかしい。少なくとも、(pure x) という関数においては、このイメージは適切でないように見える。


ならばということで、「値を関数に与える、しかるのち、関数適用により値を生み出す」という言い方をしてみる。
これにより、「(pure x) を y に適用した結果 x が得られる」を、「y を (pure x) に与える、しかるのち、関数適用により x を生み出す」と言い換えることになる。
もっと言えば、「所与のものである y に対して、アクションとして (pure x) を適用する」でなく、「所与のものである (pure x) に対して、アクションとして y を与える」というイメージである。


この場合、(pure x) の性質はどうなるだろうか? 「将来に y が与えられた場合に x を生み出す」と言える。
そして、この動作は定数的であるため、 y が何であるかは全く生み出される値に影響しない。すなわち y という値は隠蔽されることになる。
(pure x) の性質が、 y の性質を隠蔽する……ということから、「箱」の働きが連想されないだろうか。文字通り、「函数」である。
図示すれば、以下となる。



そして、(pure x) の関数としての挙動が"純粋"であるのは、箱全体の性質が不変であるから、と見ることができるのではないだろうか。


Haskell においては、関数の型は、 a -> b と記述するので、関数が、動詞的な、固定されていないもの、というイメージがつきやすいのではないか。だが、関数により生み出される値の型は b である。ならば、関数を 「a -> というアクションを受けることができる、b 型の値」と読み替えることが可能ではないだろうか。
この点については、C言語の関数のような、「 int func( int x ) 」という記法の方がイメージしやすいかもしれない。
・ func( ) の全体の型は int である。
・ func( ) のカッコ内は空白で、ここに x で表される値を与えることができる。
という具合である。


上記のような見方をすることで、関数についてのイメージがいくらかすっきりしてきたような気がする。
では…改めて、関数にとっての「文脈」と言えるものは何なのか。
これはもう素直に、 r -> の部分、すなわち、関数に与えられる値、つまり、引数、と見てしまっていいのではないだろうか。
前回、ファンクターについてまとめた際は、

つまり、ファンクターとしての関数においては、維持される「文脈」は、「どの型に適用可能か」ということ。
で、関数は、関数合成できる、という性質を持つ故に、Functor とみなせる、ということであろう。

と書いたわけだが……内容的には似たようなものなんだけど見方が違う、という感じである。


ただ、この場合は、『すごい』の pure についての説明にある「その値を再現できるような最小限のデフォルト文脈」という部分が不明になってしまう。また再考することになるかもしれないが、一旦これは置いておく。


帰ってきた Functor、関数適用 と fmap の再考

関数について一度整理しなおしたところで、では、この見方で Functor を見直すとどうなるか。


Functor は、以下の性質を満たすもの、要するに fmap に対応するものである。

class  Functor f  where
    fmap        :: (a -> b) -> f a -> f b

fmap は、リストでの map のイメージがあるので、「fmap 関数 ファンクタ値」 という形が普通であるように見えてしまうが、これは、(a -> b) を中心に見てみれば、関数((a -> b))に、ファンクタ値(f a)を与えているだけ、ということにならないだろうか。


通常の関数適用は、f x として表されるが、これは $ を使うことで f $ x と書き直せる。
さらに、中置記法でなく、2つ引数を取る形に書き直すと、 $ f x となる。
改めて見れば、$ は、関数 f と x を取って、x に f を適用する関数である。
型を確認すれば以下となる。

Prelude Control.Applicative> :t ($)
($) :: (a -> b) -> a -> b


あれれー、これって何かに似てませんかねー。
ということで、 $ 、 fmap = <$> 、 <*> を並べてみるとこうなる。

($) :: (a -> b) -> a -> b
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b

fmap を f `fmap` x = f <$> x という書き方にすれば、$ による通常の関数適用と同じ形であることが分かる。 <*> も同様。つまり、<$>、<*> は「文脈」が関わるケースでの関数適用の特殊系と見れる。


$ 、 <$> 、 <*> を同類として見て、「値に関数を適用する」でなく、「関数に値を与える」という見方をするとどうなるか?
$ は、関数に値を与える。<$> は、関数に文脈つきの値を与える。<*> は、文脈つきの関数に、文脈つきの値を与える。
となる。


ひとまず、 <*> は手強そうなので置いておいて、 $ と <$> について整理してみる。
それぞれを以下と言い直せる。(区別のため、ファンクターの型は F とする)
f $ x   : 関数適用により b 型を生み出す関数 f に a 型値 x を与えると、b 型の値が生み出される
f <$> x : 関数適用により b 型を生み出す関数 f に F a 型値 x を与えると、 F b 型の値が生み出される


???
これは、<$> によって関数 f の型が変化した、ということになる。
つまり、文脈つきの値である x が文脈を維持したまま変化した、のではなく、x の文脈が一度外されて、f に文脈が引き継がれた、という見方をすることになる。
図示すれば以下である。



……「文脈を引き継ぐ」とはどういうことか。


ついでに、<*> も同じ言い方をしてみると……
f <*> x : 関数適用により b 型を生み出す関数 f が F の文脈をもったものに F a 型値 x を与えると、 F b 型の値が生み出される


これはわからんわ……。

つづく。

関数がファンクターである、とは

Haskell をお勉強中。
『すごいHaskellたのしく学ぼう!』をつらつらと読んでいる。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

ファンクター、アプリカティブファンクター、モナド、あたりの説明を読んでいるものの、「関数 ((->) r) は、ファンクターで、アプリカティブファンクターで、モナドである」というあたりの説明が全くピンと来なかったので、解説を咀嚼する目的で自分なりにまとめてみる。
とりあえず、関数がファンクターである、ということについて。

そもそも (->) って何

(->) は型コンストラクタ。

Prelude> :k (->)
(->) :: * -> * -> *

具体型を2つ取って、具体型を1つ返す型コンストラクタ、ということになる。
返される方の具体型は関数である。
例えば、「Integer 型と Integer 型を取って、Intger -> Integer 型を返す」という動作になる。

の右側は、2引数関数の宣言のように見えるが、これは型の世界の記述なので意味が全く違う…と。まぎらわしい…。


(->) r は、これの部分適用版ということになる。
そのまんま (->) r に :k してもエラーになるが、r の部分を適当な型にしてやると :k できる。

Prelude> :k ((->) Char)
((->) Char) :: * -> *

これは具体型を1つ取って、具体型を1つ返す型コンストラクタ、ということになる。
返される方の具体型は関数である。
例えば、「Integer型を取って、Char -> Integer 型を返す」となる。


先ほどの2引数のバージョン( -> )では、任意の型Xと任意の型Yを取って、XからYへの関数型を返す、という動作だったが、
1引数のバージョン((->) r)では、最初の型が既に指定されているので、任意の型Xを取って、rからXへの関数型を返す、という動作になる。


これが、ファンクターであるそうなのである。

ファンクターとはなんぞや

ファンクターとはなんぞや。
GHCドキュメントの記述。

The Functor class is used for types that can be mapped over.


『すごい』の説明。

Functor は、全体を写せる(mapover)ものの型クラスです。


Functor 型クラスの実装。

class  Functor f  where
    fmap        :: (a -> b) -> f a -> f b

これまたまぎらわしいが、"f" は、普通の関数ではなく、型コンストラクタである。


『すごい』の説明。

どうやら fmap は、「ある型 a から別の型 b への関数」と、「ある型 a に適用されたファンクター値」を取り、「別の型 b の方に適用されたファンクター値」を返す関数のようです。

…「ファンクター値」という概念が急に出てきた。
この時点では、「Functor は、fmap 関数が適用可能な型クラスで、fmap 関数はファンクター値に関数を適用してファンクター値を返す」みたいな説明になっているのだが、「だからファンクター値って何だよ!」ってなる(翻訳したことでわかりにくくなっている?)。
「ファンクター値」というのは、Functor 型クラスの型の値、ということになるはず。上記の「fmap を適用した時に〜」という性質を満たす型の型クラスが Functor で、その値を「ファンクター値」と呼ぶ、と理解すれば良さそうである。


「ファンクター値」と言っているからアレだが、コードをそのまま読めば、「型コンストラクタに具体型が適用されてできた具体型の値」である。
この、型コンストラクタの部分が fmap の結果失われない、ということが、Functor の性質ということのようである。


例えば、

    fmap :: (a -> b) -> f a -> b

    fmap :: (a -> b) -> f a -> g b

という動作の場合は、型コンストラクタ f の部分が消えてしまっているので、Functor ではない、ということになる。


ファンクターとしての (->) r

fmap の宣言はこうだが、

    fmap :: (a -> b) -> f a -> f b

(->) r をこれに当てはめるとこうなる。

    fmap :: (a -> b) -> (r -> a) -> (r -> b)


『すごい』の説明。

この型は、a から b への関数と、 r から a への関数を引数に取り、r から b への関数を返す、と読めます。何か思い出しませんか? そう! 関数合成です!

確かに! と言いたいところだが、狐につままれたような話である。


リストや Maybe がファンクターである、ということを説明していたあたりで、

ファンクターになれるのは、箱のような働きをする型です。リストというのは、空だったり、ものがいくつか入っていたりする箱だとみなせますね。

とあったわけだが、関数に「箱のような」のイメージを適用しようとすると混乱する。


『すごい』では、ファンクターについての説明を更新し、以下としている。

他のファンクターと同様、関数ファンクターも文脈を持った値だとみなせます。 Maybe との対比で考えてみましょう。 Maybe ファンクターは、「値があるかもしれない」という文脈でした。それに対し、関数ファンクター (->) r (あるいは r -> )は、「 r 型の入力を適用すれば結果が返ってくる」という文脈を表し、それを具体化した (->) r a (あるいは r -> a )は、「 r 型の入力を適用すれば a 型の結果が返ってくる」という文脈を表しています。

…と、いうことで、この後延々と出てくる「文脈」という語が出てくる。


で、この、関数ファンクターの「 r 型の入力を適用すれば結果が返ってくる」という「文脈」は、つまりはどういうことか。
『すごい』では、fmap (*3) (+100) を例にしていたが、Int -> Int で型がそもそも変わらないので、ちと分かりにくい。
型の変換が起こる関数で、ということで、length 関数を使ってみる。


length 関数は、リストを取って整数値を返す。

Prelude Control.Monad.Instances> :t length
length :: [a] -> Int


で、この length 関数が、ファンクター型クラスの型の値だとして、fmap を適用してみる。
とりあえず、2倍にする関数。

Prelude Control.Monad.Instances> :t fmap (*2) length
fmap (*2) length :: [a] -> Int
Prelude Control.Monad.Instances> fmap (*2) length $ "sugoi"
10


次は、文字列とつなげる関数。

Prelude Control.Monad.Instances> :t fmap (\x -> "Length : " ++ (show x)) length
fmap (\x -> "Length : " ++ (show x)) length :: [a] -> [Char]
Prelude Control.Monad.Instances> fmap (\x -> "Length : " ++ (show x)) length $ "sugoi"
"Length : 5"


「 r 型の入力を適用すれば結果が返ってくる」と言われる通り、fmap の結果得られる関数が、[a] 型に適用可能である点は、どんな関数を fmap の第1引数に指定した場合も変わらない。


これは、 fmap の適用を何度行なっても維持される。

Prelude Control.Monad.Instances> (fmap (\x -> "Length : " ++ (show x)) $ fmap (*2) length) $ "sugoi"
"Length : 10"

これにより、元の関数 f について、任意の関数を fmap で適用して関数 g を得た場合、f が適用可能な型に対しては、g も適用可能である、ということになる(ただし、fmap で適用した関数が適切に型を扱う場合)。


つまり、ファンクターとしての関数においては、維持される「文脈」は、「どの型に適用可能か」ということ。
で、関数は、関数合成できる、という性質を持つ故に、Functor とみなせる、ということであろう。

リストがファンクターであるということについての再考

『すごい』では、関数がファンクターであることの前に、リスト、 Maybe をファンクターの例として挙げている。
リスト、Maybe のどちらも、「元の値」を取り出すことができるので、「箱」という比喩からコンテナ的なイメージを持ってしまいそうになる。

Prelude> [10]
[10]
Prelude> head [10]
10
Prelude Data.Maybe> Just 10
Just 10
Prelude Data.Maybe> fromJust (Just 10)
10

だが、関数の例で見た通り、「文脈」というのは値が維持されるとかそういうことでなく、もっと広い意味で見るもののようである。
そこで、リストがファンクターである、ということについて再考してみる。


リストとはそもそも何か。
『すごい』の「再帰的なデータ構造」の節での説明。

[5] というリストで考えてみましょう。これは実は 5:[] の構文糖衣です。

リストは、「空リスト」または「要素とリスト(空でもよい)を : で結合したもの」のいずれかの値を取るデータ構造です。

: という2引数関数を、5 と [] に適用すると [5] になる、ということである。
つまり、リストは、関数適用を連鎖的に行ったもの、とみなせる。

Prelude> :t (:[])
(:[]) :: a -> [a]
Prelude> :t (:1:2:3:[])
(:1:2:3:[]) :: Num a => a -> [a]
Prelude> (:1:2:3:[]) $ 0
[0,1,2,3]


リストに対して fmap を適用した場合の動作は以下である。

Prelude Control.Monad.Instances> fmap (*2) [0,1,2,3]
[0,2,4,6]

これはこう書き直せる。

Prelude Control.Monad.Instances> fmap (*2) (0:1:2:3:[])
(0:2:4:6:[])

さらに、関数適用に注目すれば、こうなる、はず。

Prelude Control.Monad.Instances> fmap (*2) (0:(1:(2:(3:[]))))
(0:(2:(4:(6:[]))))

これは、fmap によって、「 : 関数の適用」という「文脈」を維持しつつ、関数が適用された、と見ることができる。


リストの場合と比較する形で、関数に fmap を適用するケース(=関数合成)を書いてみるとこんな感じになるはずである。(実際には表示できないので手で捏造したもの)

Prelude Control.Monad.Instances> fmap (*2) ((+2) . (*4))
(*2) . ((+2) . (*4))


この対比から、意味付けを整理してみる。


・ リスト
 「リストにつなげる」という行為を再帰的に適用可能で、かつその行為の結果が構造として定着し、構造を残したままで値として扱えるもの。
  また、この構造を維持したまま、関数による操作を適用できるもの。


・ 関数
 「関数として適用する」という行為を再帰的に適用可能で、かつその行為の結果が構造として定着し、構造を残したままで値として扱えるもの。
  (また、その得られた値がすなわち関数なので、別の値に適用できる)


おそらく…こんな感じでいいのではないか。
「適用すること」が構造として定着し、特定の操作(fmap)が行われる限りはそれが維持されること、を「文脈」と呼ぶとすれば、イメージがつかめるような気がしてきた。
※ ただ、「リストにする」行為は普通の関数適用として扱えるが、「リストに関数を適用する」行為とは意味が変わってくるので、もうちょっと上手く整理するべきであるような気もする。


Haskell のプログラム全体を、複数の小さな関数が一定のルールに従って関数合成されることでできた1個の関数、として見る場合に、構造 or 文脈を保ちつつ関数を足したり引いたりできる、という性質が使われていると意識できるのかなー、というところ。


一旦ここまで。

「ホーリー・モーターズ」 映画と人生と

http://www.holymotors.jp

観た。


傑作と呼んでもいいのではないか。人生、映画そのものを描いた、という感じ。体験として満足した。
総評的なことができるかどうかは怪しいが、以下、場面を思い出しながら書いてみる。細かい記憶違いはあるかもしれないが勘弁。
完全にネタバレになったので注意。

続きを読む

『インテリぶる推理少女とハメたいせんせい』あるいは「せんせいは何故女子中学生にちんちんをぶち込み続けるのか?」


パンクなタイトルである。
そして、内容も相当にパンクである。
タイトルに「推理」と入るだけあって、ミステリ的な要素が入ってはいるのだが、自分が別にミステリに詳しくないのでその辺は語れない。ただ、本作は小説において語るということについて意識的で、その境界をガツガツ攻めてくる意欲作なので、その辺を書いてみたい。


まあ、面白かったということです。

小説における言語作用

小説において言語はどう働くか。
小説作品における言語の働きには、大きく以下の2つの方向性があると言えるのではないか。


① 言葉によってあるイメージを構成する
② 既知のイメージを言葉によって解体する(そして再構成する)


極論的には、①は②に含まれると言ってよいかもしれない。
①は、「見たことのない光景を見たい」「夢に見たような光景を見たい」という欲望に応えるものと言える。
②は、読み手が既に持つ認識を、ひいては読み手自身を解体し、再構成する。これは、ある自覚された欲望に応えるというよりは、欲望も含めて読み手の存在そのものを揺さぶる作用と言える。


どちらのケースにおいても、言葉は、あるイメージを構成/解体するものとして作用する。そこには、言葉によってもたらされる変化がある。この構成/解体に伴う変化に巻き込まれることが、読み手にとっての小説を読むことの快楽と言える。


『インテリぶる〜』における言葉の作用は、前述の区分のどちらのタイプと言えるか。②と言うべきであろう。
いわゆる普通のミステリ作品において、探偵による推理は、①の方向の言語作用であると言える。探偵による推理は、謎に包まれた事件の「真相」である。探偵が「真相」を語る時、それまで明確な像を持たなかった事件の全容が鮮やかに描き出される。イメージが構成されることの快楽を読者は味わう。
だが、本作における推理少女・比良坂れいが語るのは妄想的な、個人的な欲望・願望によって歪められた「真相」である。語り手の「せんせい」と、推理少女・比良坂による語り・推理は、互いに互いを歪め、否定し合い、「真相」は語りの渦に沈んでゆく。

二人の語り手

小説において語り手は特権的な地位を持つ者である。
本作は「せんせい」による一人称で語られているため、当然ながら語り手は「せんせい」であり、彼こそが作品における特権者となる。
だが、ミステリ作品にはもう一人の特権者、探偵が存在する。そして本作の探偵は、推理少女・比良坂れいである。


作中において、二人の特権者の力関係はどうなっているか?
地の文の語り手である以上、「せんせい」の力は揺らがない。だが、彼の力は作品内では著しく弱められている。
「せんせい」には記憶がない。「せんせい」の記憶・過去は比良坂の証言で作られる。「せんせい」は描写をさぼる。「せんせい」は欲望のままに行動し過ぎる。「せんせい」は処女以外を認識できない。
全能者たりえる一人称小説の語り手でありながら、「せんせい」は白痴的で無力なものに貶められている。
一方で、比良坂れいはどうか。比良坂は「せんせい」の欲望の対象であり、作品開始時点で文芸部唯一の、最後の処女である。比良坂は推理少女である。比良坂の推理は、比良坂の言葉は、作中現実を捻じ曲げ、「真相」を作り出す。


作品は比良坂の言葉から始まる。

「……せんせいにはわるいうわさがあるのです。文芸部の娘たちに、次々にわるいことをしているとか、どうとか。もちろんわたしは、せんせいがいいせんせいだと知っていますから、わるいことなんてするわけがないんだって信じています。けれど、この状況から顧みるに、もしかしたらもしかするのではと思ってしまったのです。

この言葉は、「せんせい」が何者かを定義する。
読者≒「せんせい」は、視線の先にいる比良坂のこの言葉によって「せんせい」に、強姦者になる。
「せんせい」と比良坂の、語られるもの・語るものの関係、及び、犯すもの・犯されるものの関係はここから始まる。

せんせいは何故女子中学生にちんちんをぶち込み続けるのか?

「せんせい」と比良坂が作品におけるキーパーソンであることは明らかである。
では、本作を駆動させる原理はどこにあるか。
これは、原題にある通り、「せんせい」の欲望である、強姦すること、にある。
では、強姦することとはどういうことか? せんせいは何故女子中学生にちんちんをぶち込み続けるのか?


「せんせい」は、処女以外を認識できない。
p186、比良坂の言。

 わるいうわさがたった後、つまりせんせいとみんなが深く結ばれた後、せんせいはみんなに対する扱いを変えました。注意深く観察していないと分からないぐらいでしたが、突き放すような態度を取るようになっていました。まるでその他大勢を扱うかのようでしかありません。なちとかをモブキャラみたいに扱っています。視界に全然入れないのです。

ならば、「せんせい」にとって強姦とは、他者を自分の世界から消すこと、殺害することにほかならない。
他者を欲望するが故に(愛するが故に)、その対象を永遠に失ってしまうのが「せんせい」である。
「せんせい」の暴力的な他者の希求は、終には「せんせい」自身を孤独の世界に落とす。
だが、その真の孤独に至る瀬戸際において、最後の他者として現れるのが比良坂れいである。


冒頭では、「せんせい」の欲望の対象でしかないかのように見えた比良坂れい。
作品が進むにつれ、舞台の「島」における状況は、比良坂によって作られたものである、と明らかになる。文芸部の女子を「せんせい」に犯させ、比良坂を文芸部最後の処女にしたのもまた比良坂である。
そして比良坂の行動原理は、「せんせい」への欲望である。


破壊的なコミュニケーションによって孤独に向かうのが「せんせい」ならば、強烈なエゴによって永遠を作り出そうとするのが比良坂である。二人の語り手は、それぞれの欲望によって破壊者と維持者の役割を得る。


作品の後半では、二人の語り手による「真相」の語りが地の文を侵食し出し、それぞれがそれぞれに作品のオチをつけようとする。そしてその度に、それぞれがそれぞれの欲望によってそのオチを否定する。
破壊者たる、読者≒「せんせい」は、比良坂の語る「真相」に屈し、愛すべき他者=比良坂と結ばれる永遠への堕ちてもよかったかもしれない。だが、本作の「せんせい」は、そのような終幕をよしとしない。


「せんせい」の欲望は、強姦=破壊的な他者の希求、である。が、これは一次的な姿に過ぎない。「せんせい」の露悪的な態度は罪悪感の裏面である。
「せんせい」の駆動原理は、「強姦がしたい」なのではなく、「自分には強姦しかできないのではないか」という疑義である。
ならばこそ、「せんせい」の対である比良坂は、「せんせい」が孤独に陥らない永遠の世界を推理によって作ることを欲望する役となった。
「せんせい」は、創造者たりえる比良坂に、自分の疑義を打ち破りつつ、自分が孤独に陥らない世界を推理して欲しかった。破壊者たる自分を解体し、あり得る姿に再構成して欲しかった。再構成の欲望、充足、否定、その繰り返し。


結末はどうか。

更生の余地がないのならばさっさとこの首を落とせ。彼女に与えられるものがないのならば呼吸をする価値もない。十三歳の恋心みたいに消えろ。

Alloy で整数を使う際のビット幅の件

結論としては、
・ デフォルトではビット幅が 3 ( -4 〜 3 ) になっている(デフォルトのスコープが Int にも適用される)
・ 指定のビット幅の範囲を超える整数についての式は結果が不定(?)
・ 特にエラー、警告は出ない。
ということのようである。
Alloy Analyzer 4.2 での話。
ビット幅の件はp132参照。


なお、明示的に Int シグネチャを指定せず、濃度制約等で整数を定数として使用してもアウトらしい。

sig B {}
sig A {
rel : set B
}

このモデルで、

pred show {
#rel > 8
}
run show

とやると、デフォルトのスコープが3なので、Aが3個、Bが3個で rel が9個になるインスタンスのみが真になるはずだが、解析の結果そうでないものが大量に引っかかる。

pred show {
#rel > 8
}
run show for 3 but 5 Int

とやると、A 3, B3, rel 9 のインスタンスのみが引っかかる。

Alloy の3項関係における多重度指定について

Alloy についてまともに使えるようになろうと、最近ああだこうだやっている。
静的なモデリングについてはほぼ納得できた気がしているのだが、動的なモデリングについては、Timeイディオムあたりでどうも理解が追いつかずに止まってしまっていた。


なぜそこで止まるかと言えば、2項関係を扱う限りは多重度指定の意味が直感的に理解できるのだが、3項関係になると、指定した多重度の意味が一気に複雜なものになってしまうから、である。自分はそうだった。
ということで、3項関係において指定した多重度がどういう意味を持っているのか、を実際に検証してみたので結果を書いてみる。
なお、使用したバージョンは、Alloy Analyzer 4.2 である。

Alloy本での対応箇所

Alloy本(『抽象によるソフトウェア設計』)で、多重度指定に関する記述があるのは以下のあたり。
・p77 3.6.5 入れ子の多重度
・p262 B.7.4 Alloy言語リファレンス 多重度


言語リファレンスの方が詳しいが、実例がないので少々理解しづらい。
3項以上の関係に関する記述としては、p263の「多重度キーワードは矢印式が入れ子になった場合でも使える」と書いてある箇所以降。これには後で触れる。

検証のやり方

・ A, B, C の3つのシグネチャを用意。
・ 3項関係、rel : A -> B -> C を宣言。
・ fact で rel についての多重度指定をさまざまなパターンで設定。
・ 各パターンについて性質を調査。

とした。
とりあえず今回は one だけで、キーワードの出現回数は1回の場合だけにした。


シグネチャの宣言まわり。
全てが1個以上ある条件にしたかったので some をつけてある。

some sig B {}
some sig C {}

some sig A {
rel : B -> C
}


対象のパターン。
one を置く位置で4パターン。カッコの付け方でそれぞれについて3パターン。計12パターン。

fact {
//rel in A one -> B -> C
//rel in A one -> (B -> C)
//rel in (A one -> B) -> C

//rel in A -> one B -> C
//rel in A -> one (B -> C)
//rel in (A -> one B) -> C

//rel in A -> B one -> C
//rel in A -> (B one -> C)
//rel in (A -> B) one -> C

//rel in A -> B -> one C
//rel in A -> (B -> one C)
//rel in (A -> B) -> one C
}


上記のパターンそれぞれについて、以下のような述語、アサーションで性質を確認した。
(util/ternary の関数を使用)

// rel に含まれない要素があるかどうか
pred existsAloneA {
some a : A | a not in dom[rel]
}

pred existsAloneB {
some b : B | b not in mid[rel]
}

pred existsAloneC {
some c : C | c not in ran[rel]
}

// A, B, C の全ての要素が rel に含まれているか
assert noExistsAlone {
not existsAloneA and not existsAloneB and not existsAloneC
}

// ある2項関係の全ての組が rel に含まれているか
assert allABInRel {
select12[rel] = A -> B
}

assert allACInRel {
select13[rel] = A -> C
}

assert allBCInRel {
select23[rel] = B -> C
}


// rel の濃度がいずれかのシグネチャの濃度と一致するか
assert relCardEqACard {
#A = #rel
}
assert relCardEqBCard {
#B = #rel
}
assert relCardEqCCard {
#C = #rel
}


// rel が存在しないことがあるか
pred noRel { no rel }

検証の結果

先にカッコの有無による挙動差についてだが、
A -> B -> C

A -> (B -> C)
では4パターン全てで同じ結果となった。
このため、デフォルトでは多重度キーワードは右結合で扱われるもののようである。
集合Aと関係B -> C の関係の多重度と、集合Bと集合Cの関係の多重度、というように入れ子で扱われているということのようである(p263の記述参照)。


以下、各パターン毎の結果について。

//rel in A one -> B -> C
//rel in A one -> (B -> C)
//rel in (A one -> B) -> C

これは、B -> C の全ての組について A が関数的、となった。
existsAloneA, allBCInRel が成り立つ。
また、カッコありの場合、どちらのパターンでも、カッコなしの場合と同じ結果となった。

//rel in A -> one B -> C
//rel in A -> one (B -> C)

これは、全ての A について B -> C が関数的、となった。
existsAloneB, existsAloneC, relCardEqACard が成り立つ。

//rel in (A -> one B) -> C

これは、A -> C の全ての組について B が関数的、となった。
existsAloneB, allACInRel が成り立つ。

//rel in A -> B one -> C
//rel in A -> (B one -> C)

これは、A -> C の全ての組について B が関数的、となった。
existsAloneB, allACInRel が成り立つ。
(A -> one B) -> C と同じ。

//rel in (A -> B) one -> C

これは、全ての C について B -> C が関数的、となった。
existsAloneA, existsAloneB, relCardEqCCard が成り立つ。

//rel in A -> B -> one C
//rel in A -> (B -> one C)

これは、A -> B の全ての組について C が関数的、となった。
existsAloneC, allABInRel が成り立つ。

//rel in (A -> B) -> one C

このパターンは少々特殊?で、
existsAloneA, existsAloneB, existsAloneC が全て成り立った。
つまり、noRel が成り立った。


これまでの流れからすれば、A -> B の全ての組について C が関数的、になりそうに見えるが、実際にはそうなっていない。
推測するに、矢印演算子の左辺が集合の場合と関係の場合で挙動が異なる、ということだろうか。


p263の記述で、

r: e1 m -> n (e2 m' -> n' e3)

という多重度制約は、e1 が集合の場合は、

all x: e1 | x.r in e2 m' -> n' e3

と、e1 が関係の場合は、

all x, y:univ | x->y in e1 implies y.(x.r) in e2 m' -> n' e3

と等価であると書かれている。
矢印の左辺が関係の場合は、imply に展開されるので、no x->y の場合はこの後の多重度指定が無視される、ということか。
(A -> B) one -> C の場合は、C から A -> B へのone制約があるので、no A -> B は成立し得ない。


考察

以上、とりあえず、one が1回出現するパターンについて確認した。


カッコの規則が確認できたのは収穫だったと思う。
後は、矢印を挟んで one と同じ側にある項が、残り2つの項の直積に対して1個、という感じでイメージしておけばよさそうである。


ちょっと面白いのは、
A -> one (B -> C)
(A -> B) one -> C
のような、あるシグネチャの集合に対して2項関係が1個、という指定が B については行えない、という点である。
要するに、A と C を直接つなぐ矢印が上記の記法では書けないからなわけであるが。
逆に、A -> C について B が1個、という書き方が複数あることになっている。


で、Time イディオムを使う場合。

静的なモデルで「あるAについてBが一つ決まる」とする場合は、以下となるが、

sig B {}
sig A {
rel : one B
}

これを動的なモデルとする場合は、こうすればよさそうである。
(というか、ホテルの客室施錠の例等でこの書き方が使われている)

sig Time {}
sig B {}
sig A {
rel : B one -> Time
}

この場合は、「あるAとTimeの組についてBが一つ決まる」となる。
ただし、この宣言が、rel にはAとTimeの組が全て含まれる、ことも含意している点には注意がいる。
all t : Time | all a : A | one a.rel.t
となる。
このモデル上では、ある Time について、ある A が rel 上にないことがない。
ただ、この点を把握した上で使う分にはさほど不自由はないと思われる。


lone の場合の挙動は上記の one の場合から類推可能と思われる。
some の場合は、もしかしたら挙動が想定と変わってくるかもしれない。
多重度キーワードが複数出るケースは、あまり考えたくない。


諸々見た感想としては、やはり3項関係は可能な限り避けたい、というところである……。


付記

3項関係についての議論があった模様。中身はまだよく見てない。
Multiplicities in ternary relations - Stack Overflow
http://stackoverflow.com/questions/12501430/multiplicities-in-ternary-relations

『虐殺器官』 罪と罰、そして死

前回(『虐殺器官』 抑圧者としての母、そして父 - doitakaの日記)に続き『虐殺器官』。前回ポストでは、母、子、父、の関係に着目したが、死、殺害、というモチーフについては正面から扱うのを避けていた。「母」が作品の裏面において支配的なモチーフであったとすれば、表面の支配的モチーフは「死」である。裏→表の順になったが、改めて、本作における「死」の扱いについて見てゆく。

「ぼく」とクラヴィスの世界

改めて作品を見る上で、「ぼく」と、クラヴィス・シェパードを注意して区別するようにしたい。
「ぼく」は作品の語り手であり、作品世界の創造者である。作者、あるいは、読者と同一視し得る存在である。
ラヴィス・シェパードは、「ぼく」が空想する架空の人物、キャラクターである、と見れる。
ラヴィス・シェパードは、あまりにも映画的・ゲーム的すぎる。つまりはフィクション的すぎる。日本語で書かれて、2000年代の日本に発表された作品において、米軍特殊部隊のナイーブな青年兵士という人物造形は、あまりにフィクションとして「日常的」である。「ぼく」は本当にクラヴィス・シェパードだろうか? そこにある種の断絶が、空想する・空想される関係が存在する、と見るのが適切であろう。
では、「ぼく」がクラヴィスを空想していたとして、クラヴィスの役目は何だろうか?


ラヴィスが生きて、各種任務を行う世界、これを「クラヴィスの世界」と呼ぶことにする。クラヴィスの世界は、「ぼく」によって空想される世界である。
ラヴィスの世界と対置すべきものがあるとすれば、それは死者の国である。


本作において支配的な他者である「母」は、「誰」の母であるか?
ラヴィスの世界の設定からすれば、「母」はクラヴィスの母であるに相違ない。だが、クラヴィス以上に、語りの主体である「ぼく」が、「母」を強く意識して世界を構成(=空想)している。クラヴィスに母がいる、というより、「ぼく」が「母」と相対する上で、クラヴィスというキャラクター、クラヴィスの世界を生み出した、と見るべきである。(死者の国において、「母」は「ぼく」を「クラヴィス」ではなく「息子さん」と呼ぶ)


対置的に見るならば、死者の国は、「母」の支配する世界である。一方で、クラヴィスの世界は、「母」不在の世界である。クラヴィスの世界は、その語りの始まりの時点から「母」を失っている。
死者の国の有、クラヴィスの世界の無。


作品の記述は、死者の国の光景から始まる。

 ここは死後の世界なの、とぼくは母さんに訊く。すると、母さんはゆっくりと首を振った。子供のころ、そうやってぼくの間違いを正したあのしぐさで。
「いいえ、ここはいつもの世界よ。あなたが、わたしたちが暮らしてきた世界。わたしたちの営みと、地続きになっているいつもの世界」
 そうなんだ、とぼくは言う。安心して涙がこぼれた。かなたの行進には見慣れた顔がいくつもある。小児ガンで逝ったベンジャミン、頭を吹き飛ばした父さん。
 すると、母さんはぼくの手をとって、行進へとみちびいてくれる。
「さあ、いきましょ」
 ぼくはうなずき、母さんとともにかなたの死者たちへと歩いてゆく。

まるで、何かの作品のラストシーンであるかのような、大いなる合一、安らぎ。
「ぼく」が死者となって、「母」を含むすべての死者たちと同じ世界に在る、という幻視。
これは何か?


ラヴィスの世界は、死者の国と比べれば「リアル」な、我々読者の日常に近いと思われる世界である。少なくともそのような世界であるところから語りは始まる。
ラヴィスは、その世界の中で、死に最も近い存在として描かれる。
彼は殺人者である。
何故人を殺すのか?
虐殺を止めるため。
本当に?


ラヴィスに付された「ぼく」の願望は何か?
死に触れること。そのために彼は兵士として造形される。
死に触れたいのであれば、黙ってさっさと一人で死ねばいいのではないか?
死に意味を見出すこと。
死の意味とは?
殺すことの罪、それへの罰と赦し。
それで?
死者の国の大いなる安らぎ。


ラヴィスの世界は、最初から無意味な死に覆われている。
「母」の死
・組織の命でクラヴィスが殺した人々
・遠くの国での虐殺

元准将の発言。

「たのむ、教えてくれ、俺はなんで殺してきた」

無意味な死と理由のない殺害。
これらこそ、「ぼく」=クラヴィスが抗うものである。
意志をもって行われる殺害、その罪を背負うこと、その罪が罰され赦されること。大いなる和解と合一。


ラヴィスは、組織の命により、ジョン・ポール、そして、「母」の模造品のルツィアを追う役目を得る。
ジョン・ポールは、意志を持って世界中の人間を殺害してきた人物として造形されている。ジョン・ポールは、「ぼく」がクラヴィスというキャラクターを通して到達しようとした、理想像的なキャラクターと見れる(虐殺の文法=ことば、は、おそらく「ぼく」にとって最もリアリティのある力だったのであろう)。
ジョン・ポールがなぜ理想的か? 彼がこれから世界中の人間を虐殺できるから?
おそらくそうではなく、彼が、既に起きた虐殺の罪を背負っているから、であろう。
ジョン・ポールは全ての罪の概念である。それを、「ぼく」の肥大化した罪の意識の具現化したもの、と言い換えてもよい。
「ぼく」の罪の意識は、ミクロレベルでは母の殺害から始まり、ジョン・ポールを経由することでマクロな世界中の罪に接続される。「ぼく」=クラヴィス=ジョン・ポールは、世界中の罪を集約する観念的装置となる。
ラヴィスの世界では、そこにルツィアが配置される。ルツィアの視線は、クラヴィス、ジョン・ポールを捉え、そこに罪の存在を認める。そして、その罪に罰と赦しを与える。ルツィアが鍵である、大いなる合一への。


「ぼく」の始発点のクラヴィス、クラヴィスを導き、全ての罪へと接続する先導者となるジョン・ポール、罪に罰と赦しを与えるルツィア。三者の合一は、あの死者の国の大いなる合一につながるはずであった。
しかし、語り手たる「ぼく」は、彼等を無意味な死に屈服させる。


「母」、地獄、真空

「母」のいる死者の国の描写は、三度行われる。
最初の死者の国では、穏やかな死者同士の和解の姿が描かれる。
二度目の死者の国で「母」は「自分が肉だということ」を受け入れろ、と言う。
三度目の死者の国では、「母」は「ぼく」の母殺しの罪に赦しを与えることを拒否し、「ぼく」がそれまでに犯した殺害の罪から逃れることを非難する。


「母」の視線は、クラヴィスの世界の外にあり、そこから「ぼく」を見つめ、追い立てる。
三度目の死者の国は、第三部の冒頭、クラヴィスの物語がジョン・ポール、ルツィアを巡る「本題」に入る直前に位置している。
三度目の死者の国で、「母」は「ぼく」を抑圧するもの、恐怖の対象として描かれる。端的には、クラヴィスの世界での出来事は、全て、この「母」の視線から逃れるための茶番でしかないとすら言える。
「母」は「ぼく」が罪から逃れることを非難した。その結果どうなったか。クラヴィスの世界に、世界中の罪を背負う装置としてジョン・ポールが現れた。
「母」は「ぼく」に赦しを与えてくれなかった。その結果どうなったか。クラヴィスの世界に、「ぼく」=クラヴィスに赦しを与える装置としてルツィアが現れた。
強い他者としての「母」。クラヴィスの世界の背景には常に「母」の視線がある。


ジョン・ポール、ルツィアはどうなったか? 二人とも、あっけなく、無意味に死ぬ。
「ぼく」=クラヴィスが必死に意味を見出そうとしていた死は、その無意味さ、空虚をさらけ出す。
アレックス、ウィリアムズ、ルツィア、ジョン・ポール。クラヴィスの物語を彩ったキャラクターたちは死に、「ぼく」=クラヴィスは孤独を得る。


p381

 だが、ルツィアは死んでしまった。もはやぼくを罰したり赦したりしてくれる人はどこにもいなくなってしまった。
 いま、ここにある地獄。ぼくは自分という地獄に閉じこめられた。地獄はここにあるんですよ、というアレックスの声。そうとも、いまぼくは最悪の地獄に堕ちた。罰せられることを、その果てに赦されることを期待して、こんなアフリカの奥地にやってきたのに、そこに着いたとたん罰も赦しも壊れて消えてしまった。
 これこそが罰なのだろうか。死ぬまでの時間ずっと、罪を抱えて彷徨うことが。


p384

アレックス、ルツィア、ジョン・ポール。そのすべてが遠い過去の出来事のように思い出された。あのとき覚えたはずの感情、あのとき得たはずの洞察。そのすべてがリアリティを失って、壁に隙間なく貼りつけられたスナップ写真のように、全体のディテールのごく一部へと還元されてゆく。


罪だけが残り、罰も赦しもない世界。無意味な死の世界。
死に意味がなければ、死者の国の大いなる合一という幻想が虚影であることが明らかになってしまう。


「ぼく」=クラヴィスにとどめを刺すのは、「母」ライフログである。
死者の国からの「母」の視線によって駆動したクラヴィスの物語。これは、クラヴィスが家で母からの視線を感じていた、という物語中の設定と同期するものである。
もう一度問う。死者の国の大いなる合一とは? 端的に言えば、他者たる「母」と「ぼく」の和解である。
ラヴィスの物語は「母」の視線により駆動した。つまりは、「母」への渇望、「母」との和解という望みが「ぼく」を動かした。死者の国とは、「ぼく」の願望の至る場所である。

では、「母」ライフログとは何であろうか? それは「ぼく」の綴った物語たち(死者の国、クラヴィスの物語)と同じではないか。つまり、ライフログとは「母」の願望を具現化したもの、「母」自身の死者の国にほかならないのではないか。
他人の願望はただグロテスクである。
「母」の死者の国が「ぼく」の死者の国と別もので、そこに「ぼく」の居場所がないということ。この事実は、死者の国が、実現されることのない個人の妄想でしかないことを「ぼく」に突き付ける。
「母」の視線によって駆動していたはずのクラヴィスの物語は、ここでその原動力を失う。
あの大いなる合一は幻でしかなかった。
和解は永遠に為されない。


死者の国の合一=「母」との和解、が目的であったとすれば、虐殺の文法による虐殺とその罪を背負うことは手段に過ぎない。全世界的な虐殺という空想的な極限にある罪、つまりは全ての罪を背負うということ。全ての罪を背負ったフリをしても死者の国にたどり着けなかった滑稽な「ぼく」。
目的を失ったクラヴィスの物語は絶望に終わるはずである。だが、エピローグで、「ぼく」=クラヴィスは、まるで余興であるかのように虐殺の文法を振るう。
ここにおいて、目的と手段が転倒した、と言えるだろうか?


本作において「ぼく」を駆り立てるものを追った時、たどり着くのは「母」の存在である。
だが、「ぼく」と「母」の葛藤劇を描くのに、ここまで死、殺害のモチーフを色濃く出す必然性がどこにあるか?


エピローグで、「ぼく」=クラヴィスによって、クラヴィスの世界は死に覆われる。
それは、「ぼく」が夢見た、甘美で満たされた死者の国ではない。また、抑圧者たる「母」が勝利した世界でもない。
無意味で空虚な死によるクラヴィスの世界の終焉、それは即ち、「ぼく」の葛藤の終焉である。


ひとつ望みがあるとすれば、最初の死者の国で、「ぼく」が死んでいた、という点だろうか。
まだ生きているクラヴィス。あの世界でクラヴィスが死んだ後、彼の望む死者の国に行けないとも限らない。
虐殺者がいなくても、他者がいなくても、最後には支配的な死がやって来て、それに「ぼく」は屈服する。
真の死と沈黙、あるいは安らぎ。


まとめ

死から出発したつもりで、結局、母の話題になってしまった気がするが……。
一旦ここまで。