ES6のジェネレータはHaskellのdo記法ほど強力ではないという話

curiosity-driven.org
postd.cc

この記事では、ES6のジェネレータを使って、Haskellのdo記法を模倣したdoM関数を定義し、ジェネレータを使ってモナドを取り扱えることを示している。しかし “The same routine can be used with other monads like the Continuation monad” という記述に反し、実はdoMと一緒に使えるモナドと、使えないモナドがある。

話を簡単にするため、以下ではECMAScriptのプロトタイプチェーン機能を使わないでプログラムを書くことにし、doMには、モナドを表現するオブジェクトを、引数として別途渡すことにする。

function doM(m, gen) {
  function step(x) {
    var y = gen.next(x);
    if (y.done) {
      return y.value;
    }
    return m.bind(y.value, step);
  }
  return step();
}

具体的に、ふたつのモナドOMGMを定義する。OMはOptionMonadの略で、GMはGeneratorMonadの略だ。

var OM = {
  unit: function(x) {
    return {tag: "Some", value: x};
  },
  bind: function(n, k) {
    if (n.tag === "None") {
      return {tag: "None"};
    }
    return k(n.value);
  },
};

var GM = {
  unit: function*(x) {
    yield x;
  },
  bind: function*(g, k) {
    for (var i of g) {
      yield* k(i);
    }
  },
};

このとき、OMに対してはdoMを適用できる。

var x = doM(OM, function*() {
  var a = yield OM.unit(2);
  var b = yield OM.unit(3);
  return OM.unit(a * b);
}());

console.log(x); // ==> Object { tag: "Some", value: 6 }

var y = doM(OM, function*() {
  var a = yield OM.unit(2);
  var b = yield {tag: "None"};
  return OM.unit(a * b);
}());

console.log(y); // ==> Object { tag: "None" }

一方で、GMに対してdoMを使うと、例外が出てしまう。

var z = doM(GM, function*() {
  var a = yield function*(){ yield 2; yield 3; yield 4; }();
  var b = yield function*(){ yield 5; yield 6; }();
  return GeneratorMonad.unit(a * b);
}());

try {
  for(var i of z) {
   console.log(i);
  }
} catch (e) {
  console.log(e); // ==> TypeError: k(...) is undefined
}

なぜかといえば、GM.bindは第2引数k複数回呼び出す可能性があるからで、一方、doM内で定義されている関数stepは、ジェネレータの呼出しに副作用を使うことを前提としていて、複数回呼び出されることを考慮しない作りになっているという点が問題となっている。この問題を修正するには、途中まで実行したジェネレータを複製することができる必要があるが、ES6のジェネレータにそのような機能はないようなので、結局ジェネレータを使ってどのようなモナドにも対応したdoMを実装することはできないということになる。

比較用に、doMを使わない場合のコードも載せておく。

var w = GM.bind(function*(){ yield 2; yield 3; yield 4; }(), a =>
        GM.bind(function*(){ yield 5; yield 6; }(), b =>
        GM.unit(a * b)));

for(var i of w) {
  console.log(i);
}

「抽象化」を抽象化する 〜 nopは確かに抽象化のひとつの形であるという話のメモ書き

さて、以上の議論を踏まえた上で、「世界一抽象化されたコード」というのを今から書いてみましょう。一瞬でかけます。

# nop

上にあげたものがそうです。つまり、「なにもしない」というコードこそが、世界一抽象化されたコードです。

http://nekogata.hatenablog.com/entry/2015/08/05/001742

これが本当に抽象なのか? と疑問に思う人がいるのだけれども、これは確かに一種の抽象化ではあるのだ。これが抽象化だと思えないのは、このnopの例自体が、具体的にどういう抽象化を前提としているかを明示していない、抽象的な例だからだ。「抽象化」という概念それ自体が抽象的だ。関数は、機械に扱える抽象化の機構のひとつなのだけれども、だからといって関数だけが抽象化ではない。

抽象化というのは、プログラムを書くのに使える概念であるという以前に、物の考え方としての概念だという側面がある。このnopの例は、少なくとも、もはやRubyが形式化しているレベルの抽象を越えてしまっていて、それは計算機にとっては意味を持たない(具体的に計算できない)抽象化だ。Ruby処理系に# nopというコード自体を渡しても、これはコメントを含む空のプログラムだと具体的に解釈されるだけであって、全く抽象性を持たない。だけど、そういう、機械にとって意味を持たない抽象化でも、人間にとっては意味のある何かを抽象している場合がある。コメント行自体もそうだし、アルゴリズムの本などが載せている擬似コードなどは、機械が読めずとも人間が読める、抽象的なコードだ。その抽象的なコードは、人間が適宜解釈し、具体的なプログラミング言語で実装することができる。

条件分岐if C then A else Bを抽象化して、非決定性の分岐A ⊕ Bとして考える、といった話と似ている。(抽象化というより、近似と言ったほうがいいのかもしれないけど。あるいは、抽象化というのは、別の視点を変えれば、近似と見ることができる。)

普通プログラマが抽象化と言ったら、機械が扱える範囲での抽象化だけ考えているんだ、と言うかもしれないけど、どういう種類の抽象化を機械が扱えるかというのは、曖昧だ。擬似コードだって、十分に形式化されていれば、処理系を実装して実行することができる。

まとまらないけど、メモ書きだからこれで終わり。

CoffeeScriptで代数的データを表現する

関数型言語ではポピュラーな機能である、代数的データ型を愛してやまない人は多いだろう。しかし悲しいことに、CoffeeScriptは、代数的データ型を持っていない。今回は、オブジェクトを使って代数的データの条件分岐を表現する方法について書こうと思う。

次のコードは、数式の文字列化や評価を行うプログラムだ。

# 分岐関数
match = (x, c) -> x.apply(c)

# 構築子
num = (x) -> ->@num(x)
add = (x, y) -> ->@add(x, y)
mul = (x, y) -> ->@mul(x, y)

# 数式 1 + 2 * 3
exp = add(num(1), mul(num(2), num(3)))

# 文字列化
p = (exp) -> match exp,
  num: (x) -> String(x)
  add: (x, y) -> "(" + p(x) + ")+(" + p(y) + ")"
  mul: (x, y) -> "(" + p(x) + ")*(" + p(y) + ")"

# 評価
ev = (exp) -> match exp,
  num: (x) -> x
  add: (x, y) -> ev(x) + ev(y)
  mul: (x, y) -> ev(x) * ev(y)

console.log p(exp) + " = " + String(ev(exp))

実行すると、次のように表示される。

(1)+((2)*(3)) = 7

構築子

構築子は、次の形をしている。

c = (x...) -> ->@c(x...)

(仮引数列) -> 式は関数を作る構文、-> 式は引数のない関数をつくる構文で、@メソッド名(実引数列)JavaScriptthisメソッドを呼び出す。つまり構築子cは、this.cx...を引数として呼ぶクロージャーを返す関数だ。

分岐関数

条件分岐は関数matchに、代数的データと、分岐ごとの処理を表すオブジェクトを渡して行う。

分岐関数内では、渡された代数的データ(実体はクロージャー)をオブジェクトに適用している。

match = (x, c) -> x.apply(c)

こうすると、クロージャーがオブジェクトの適切なメソッドを呼び出し、条件分岐を行ってくれる。

もうひとつの方法

別の方法として、次のような分岐関数と構築子を使う方法が考えられる。

# 分岐関数
match = (x, c) -> c[x[0]].apply(c, x[1..])

# 数式の構築子
num = (x) -> ["num", x]
add = (x, y) -> ["add", x, y]
mul = (x, y) -> ["mul", x, y]

Debug the Haxe Compiler with OCamlDebug

1. Apply the following patch to the Makefile:

diff --git a/Makefile b/Makefile
index e912e15..1f6c71f 100644
--- a/Makefile
+++ b/Makefile
@@ -80,7 +80,7 @@ libs:
        make -C libs/objsize OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
 
 haxe: $(MODULES:=.$(MODULE_EXT))
-       $(COMPILER) -o $(OUTPUT) $(NATIVE_LIBS) $(NATIVE_LIB_FLAG) $(LFLAGS) $(LIBS:=.$(LIB_EXT)) $(MODULES:=.$(MODULE_EXT))
+       $(COMPILER) -g -o $(OUTPUT) $(NATIVE_LIBS) $(NATIVE_LIB_FLAG) $(LFLAGS) $(LIBS:=.$(LIB_EXT)) $(MODULES:=.$(MODULE_EXT))
 
 haxelib:
        (cd $(CURDIR)/extra/haxelib_src && $(CURDIR)/$(OUTPUT) haxelib.hxml && nekotools boot bin/haxelib.n)

2. Build the compiler with the following command:

make BYTECODE=1

3. Execute ocamldebug:

ocamldebug ./haxe [arguments]
% ocamldebug ./haxe
	OCaml Debugger version 4.02.1

(ocd) break @ Main 979
Loading program... done.
Breakpoint 1 at 3223236: file main.ml, line 980, characters 2-29726
(ocd) run
Time: 69442 - pc: 3223236 - module Main
Breakpoint: 1
980 	<|b|>let usage = Printf.sprintf
(ocd) n 20
Time: 69757 - pc: 3223608 - module Main
1000 	Common.define_value com Define.HaxeVer (float_repres (float_of_int version /. 1000.))<|a|>;
(ocd) p version
version: int = 3300
(ocd) rev
Time: 69442 - pc: 3223236 - module Main
Breakpoint: 1
980 	<|b|>let usage = Printf.sprintf
(ocd) prev
Time: 69441 - pc: 3198700 - module Main
637 			<|b|>init ctx;
(ocd)

You can even trace back to the past!

Check the debugger commands at The debugger (ocamldebug).

Happy hacking!

哲学無用論と哲学の価値

哲学は役に立たないのではないか、という批判はソクラテスのむかしからあるようだ。(理想国のあり方と哲学の役割──『国家』第5-7巻)そういう哲学無用論に反論する方法のひとつに、哲学の有用性を具体的に説くというものがある。

logmi.jp

でも、哲学が役に立った例を具体的にいくら挙げたところで、“本質的に”哲学の有用性が示されたことにはならない。どれも、特定の哲学の考えが有用であったというだけで、相変わらず、何の役に立つのか分からない哲学もある。すべての哲学に、その用途をあてがうのは不可能だろう。

有用な諸科学も、源流を辿れば哲学に由来しているのだから、今の哲学もいずれ有用となるはずだとも考えられる。ソクラテス「星を見つめる男」の比喩にしたって、天文学という一見無用に見える学問が航海術に役立つということに喩えている。アインシュタイン一般相対性理論全地球測位システムGPS)の構築に不可欠なのだから、理論物理学は有用であるという話と変わらない。しかし、このような考え方は、楽観的だ。

哲学も役に立っているという論で救われるのは役に立つことが明らかになっている哲学だけだし、将来役に立つという説明では、悲観的なひとを納得させられないだろう。哲学を、有用性の観点から価値付けようとする試みは、そもそも無理があると思う。ある種の哲学は実際に無用で、その前提は覆らない。

それでも、哲学には価値がある。その価値とは、希哲学 philosophy という名が示している通りの価値だ。哲学に価値をもたらしているのは、知ることへの強烈な欲求だ。人間は、食欲や睡眠欲と並んで、知ることに対して抗いがたい欲求を持っている。食事は諸活動に必要だが、同時に食事自体が楽しみだ。食事に興味を持たず、完全に単なる手段とみなし、実用性・合理性を追求する人間は、極少数派だろう。(もしいるとしたら、そいつはたぶん哲学者だ。食事する哲学者の問題 - Wikipediaそれかサンドウィッチ伯爵か。結局、どの欲求が一番強いのか、という話だ。)

肉を食らうことも本を食らうことも等しく人間的で、健康に関係し、価値のあることだけれども、役にも立たない本を食らうことに何よりも強い満足感を感じる人間というのは、やはり少数派なのだろう。

「哲学は役に立つの?」「まあ、世の中には哲学を食らう人間もいるのだ。」

プログラムを哲学する 1. 言及

これから書くのは、言葉や論理と、その意味に関する話だ。フレーゲらによる、物事を厳密に考える言葉の探求は、現代論理学や分析哲学の出発点になった。まずは、その哲学を探りながら、関数プログラミングの話でよく耳にする「参照透過性」という概念を理解することを最初の目標にしたい。

言及

Reference (Stanford Encyclopedia of Philosophy)

普通、記号には表す対象が存在している。記号と記号が表す対象との間にある関係を、言及(reference)という。*1たとえば、「東京タワー」や「港区にある電波塔」という言葉は建造物の《日本電波塔》への言及だし、「港区」や「東京タワーのある区」という言葉は場所の《東京都港区》への言及だ、などという。*2このような、記号の意味とは言及対象のことなのだという考えは、いろいろある意味の捉え方のうちのひとつだ。(直接言及論 Direct reference theory - Wikipedia, the free encyclopedia

意味の合成性原理

Compositionality (Stanford Encyclopedia of Philosophy)

複合表現の意味がその表現の構成要素の意味のみに依拠し決定されるという原理を、意味の合成性原理(compositionality)という。意味の合成性原理は、複合表現の一部分を、同じ意味を持つ別の表現に置き換えたときも、複合表現全体の意味も変わらないということを主張している。

たとえば、次の文を考える。

1. 東京タワーの高さは東京スカイツリーの高さよりも小さい。

文1の「東京タワー」という部分を、意味が同じ「港区にある電波塔」に置換すると、文2ができる。

2. 港区にある電波塔の高さは東京スカイツリーの高さよりも小さい。

意味の合成性原理から、文1と文2は同じ意味だと主張できる。意味の合成性原理は、代入の根拠となっている。

「意義と意味について」

ゴットロープ・フレーゲは、「意義と意味について」(ドイツ語原題: Über Sinn und Bedeutung)において、文の意義(Sinn)と意味(Bedeutung)の区別を主張した。*3

http://www.amazon.co.jp/%E7%8F%BE%E4%BB%A3%E5%93%B2%E5%AD%A6%E5%9F%BA%E6%9C%AC%E8%AB%96%E6%96%87%E9%9B%86%E3%80%881%E3%80%89-%E5%8F%8C%E6%9B%B8%E3%83%97%E3%83%AD%E3%83%96%E3%83%AC%E3%83%BC%E3%83%9E%E3%82%BF-G-%E3%83%95%E3%83%AC%E3%83%BC%E3%82%B2/dp/4326198761www.amazon.co.jp

意義

意味とは言及対象だと考えると、「明けの明星は宵の明星と同じものだ」という文の意味と、「明けの明星は明けの明星と同じものだ」という文の意味は、意味の合成性原理から、同じだということになる。しかし、このふたつは本当に同じ意味なのだろうか。前者は何か新しい知識を与えてくれるのに対して、後者は単なる同語反復にすぎない。フレーゲはそのことを、異なる認識価値(Erkenntniswert)を持っていると表現した。認識価値が異なる文が、同じ意味を持っているということになるが、これはどう考えればよいのだろうか。

フレーゲは、記号に結びつくものとして意味の他に意義があると考えた。「明けの明星」と「宵の明星」は、意義は異なるが、どちらも《金星》を意味している。フレーゲは、通常の命題文の意味は真理値だと考えた。*4「明けの明星は宵の明星と同じものだ」という文と「明けの明星は明けの明星と同じものだ」という文も、意義は異なるが、どちらも《真》という対象を意味している。

副文の意味

フレーゲは認識価値との結びつきである意義と、言及対象との結びつきである意味の区別を主張する中で、同じ表現であっても意味が異なる場合について考えを進めており、副文の意味は真理値ではない場合があると考えている。

コペルニクスは、惑星の軌道は円であると信じた」という真の文について、「惑星の軌道は円である」が偽だからといって、「東京タワーは東京スカイツリーより高い」という別の偽の文を代入して「コペルニクスは、東京タワーは東京スカイツリーより高いと信じた」に変えては、文の真理値が変わってしまう。フレーゲの考え方に従えば、「コペルニクスは、東京タワーは東京スカイツリーより高いと信じた」という文中の「東京タワーは東京スカイツリーより高い」の意味は、真理値ではなく思想だということになる。

このような、同じ表現でも意味が異なる場合があるという考えは、今後referential transparencyの話につながってくる。

意味をもたない表現・意味が定まらない表現

フレーゲは、名詞句を作る副文についても考えを進める。論理的な議論をする上で、表現の意味が一意に存在するということは重要だった。言語のすべての表現について、その意味が一意に定まる性質を、言語の完全性という。

たとえば、「0/0」や「4の平方根」という表現は意味を持たなかったり、複数持っていたりするので、解析学で使われている言語は不完全だ。フレーゲは、言語の不完全性を約定(Festsetzung)によって解決しようとした。フレーゲは「発散無限級数は数0を指示するという約定」を例に挙げている。要は、どのような表現も意味が一意に定まるように、言語を設計するということだ。

この考え方はプログラミング言語ではよく見られるもので、たとえばJavaScriptでは0/0の値はNaNMath.sqrt(4)の値は2と決まっている。プログラミング言語の意味とは式の値だと定義すれば、どのプログラムも一意に値が定まるということがプログラミング言語の完全性ということになる。*5

コラム: さまざまな用語

言葉や記号や意味について議論するのに使えそうな言葉を挙げてみる。

sense, reference, referent, denotation, connotation, extension, intension, signifier, signified, expression, representation, token, idea, image, sign, interpretant, identifier, value, entity, object.

昔から、これらの言葉を使った様々な論が出されているが、その考え方すべてを簡単にまとめることはできそうもない。似た意味で異なる言葉を使っていたり、同じ言葉が少し異なる意味で使われていたりする。おいおいこれらの言葉の関係について考察をしようと思うが、とりあえずは必要な言葉を定義することにする。

*1:referenceの訳語は悩んだ。指示、参照、言及などが候補に挙がった。どの言葉にしても日常の用語と違った意味に聞こえてしまうが、命令を印象させる指示や、物事を参考にすることを印象させる参照などよりは、より自然な表現に聞こえるだろうということで、言及を選んだ。情報科学では、referenceの訳語に参照を使う。訳語に言及を使うことは他ではあまりないが、self-referenceという用語は自己言及と訳されることが多いので、突飛な訳語というわけでもないと思う。

*2:2016年9月3日追記: 英語のreferenceはreferentの意味で使われることがある点で、日本語の「言及」と意味合いがずれているので注意がいる。「表示」と訳されるdenotationも、意味するところは「表示されるもの」なので難しいところだ。

*3:SinnもBedeutungも類義語だが、日本語ではSinnを意義、Bedeutungを意味と訳し分ける場合がある。英語ではSinnをsense、Bedeutungをreferenceと訳すことがある。

*4:命題の真理値は人間の信念に関係なく客観的に決まっているという考えが根底にある。

*5:この定義の上では、JavaScriptは完全でない。たとえば、例外を投げる場合や、無限ループが発生する場合に、式は値を持たない。完全・不完全を議論する上では、何を意味だと考えているかに注意する必要がある。

プログラムを哲学する 0. プログラムと哲学の関係

僕は、プログラムを哲学したい。その動機のひとつに、用語の統一がある。現状、プログラムにおいて使われる用語は、対象言語によって色々と異なってしまっている。たとえば、似たような概念に、あるプログラム言語ではポインターという用語を使い、別の言語ではリファレンスという用語を使うといった場合がある。インターフェースとトレイトは同じなのかどうか。クラスと型クラスはどうか。同じ概念に違う名前を付けていたり、違う概念に同じ名前を付けていたりするので、混乱が甚だしい。

このような用語の混乱の下では、その場その場でアドホックに用語を定義し直すしかないが、そうすると他の場面で使われた用語との関係性がよく分からなくなってしまう。プログラムを哲学することで、このようなバベル的混乱の状況を変えられるのではないかと思っている。

動機のもうひとつは、プログラムするという行為の実態をより明確に捉えたいということだ。今日プログラミング教育の必要性が主張されているが、プログラムを教えるとはその実何を教えることになるのかについて、意識を深めたい。「プログラムする」というのは、単に機械に指令を与えるということなのだろうか? プログラミング教育は、単に技術者不足を解消するために行うものであるべきなのだろうか? そのようなことを考えたいのだ。

歴史を辿れば、計算機科学、数学、論理学、分析哲学言語学という諸分野は、19世紀末における現代論理学の創始というイベントで交叉する。各分野にまたがって、フレーゲ、ラッセル、クワインといった名前や、各種共通する用語を目にすることができる。

しかし、今日では各分野に分化してしまった。ちゃんと情報だとか計算機に関する哲学をやっている人間も存在しているのだろうけれども、そういう分野をフォローしている人間は、計算機を単に工学の対象として解説する読み物に比べると、哲学的観点も絡めて語っているものは少ないように思う。

この連載(になる予定)では、まず分析哲学の黎明期における関係性を探ってみたいと思う。

絵文字 WHITE FLOWER 💮 を比べてみる

寿司の絵文字を比較して心を落ち着かせる | プログラミング生放送
Pile Of Poo! ウンコーな絵文字を比較してみた! - SHII.NET(しぃねっと)
絵文字比較がブームなので、ここでは U+1F4AE WHITE FLOWER 💮 を比較してみようと思います。

Unicode code chart

Unicodeのチャートでは次のような形で載りました。Googleらの提案段階 (emoji4unicode - Emoji for Unicode: Google Emoji private use mapping data and tools - Google Project Hosting) からこのグリフのようです。
f:id:mandel59:20150421172817p:plain:h128
U+1F4AE には brilliant homework というコメントが付いています。

Apple Color Emoji

Apple Color Emojiでは、これが「大変よくできました。」スタンプの形で実装されました。
f:id:mandel59:20150421173116p:plain:h128

Twemoji (Twitter)

桜花のスタンプ、文字抜き。
f:id:mandel59:20150421173726p:plain:h128

KDDI絵文字(旧)

Unicodeに収録されたU+1F4AE WHITE FLOWERは、KDDIの絵文字がソースなのですが、なんとKDDIでは花丸です。
f:id:mandel59:20150421172602g:plain:h128

au/docomo共通絵文字

共通絵文字も花丸です。
f:id:mandel59:20150421174332p:plain:h128

Noto Color Emoji (Google)

Androidの絵文字も花丸です。Google日本語入力でも「はなまる」で💮が出ます。
f:id:mandel59:20150421173317p:plain:h128

Segoe UI Emoji (Windows)

これはなんなんですかね。
f:id:mandel59:20150421173603p:plain:h128

Emoji One

よく分かりません。
f:id:mandel59:20150421173829p:plain:h128
分からなすぎるのでissue投げました。U+1F4AE WHITE FLOWER fails to catch its original sense · Issue #33 · Ranks/emojione · GitHub

まとめ

WHITE FLOWERをスタンプで実装しているところと花丸で実装しているところとよく分からないところがある。
絵文字は闇。

Source Han Sans 1.002 をダウンロードする

Source Han Sans (源ノ角ゴシック)バージョン1.002がリリースされました。次のページからダウンロードできます。
adobe-fonts/source-han-sans at release · GitHub
基本的にはSubsetOTFディレクトリの中のSourceHanSansJP.zipをダウンロードして使えばOKです。

SourceHanSansReadMe.pdfの中には、どれを使えばいいのか迷った人のためのフローチャートがあります。下の図は日本語訳です。
f:id:mandel59:20150421085759p:plain
どの環境でもOKなのはSubsetOTFだけなので、DTPで使うなど、他人とデータをやりとりする必要があるならSubsetOTFを使ったほうが無難です。

以下、各コンフィギュレーションの簡単な説明です。

Subset OTF (region-specific subset OTF)
各地域で使う文字だけを収録しています。4地域(CN, JP, KR, TW)のコンフィギュレーションがあります。
OTF (language-specific OTF)
すべての文字を収録しています。デフォルトの言語の違いで、4言語(SC, TC, J, K)のコンフィギュレーションがあります。また、それぞれについて、英数字が半角のコンフィギュレーションがあります。
OTC
全言語コンフィギュレーションがひとつのOTCファイルに収録されています。トータルのファイルサイズを抑えることができます。使える環境が限られます。
Super OTC
全ウェイト・言語コンフィギュレーションがひとつのOTCファイルに収録されています。トータルのファイルサイズをより抑えることができます。使える環境が限られます。

新しい絵文字を提げて iOS 8.3 がやってきた

Appleが、ドラフト段階の絵文字修飾子を実装したiOS 8.3をリリースした。パブリック・ベータ版とは、Genericな肌色の絵文字の髪の色が、黄色に変更されている点が違う。これは、黄色がアジア人をイメージしたものだというクレームがあったので、Yellow is ethnic-neutral colorを、髪の色にも敷衍させた解決策だろう。金髪に見えなくもないが、悪くはない。少なくとも、アジア人に見えるというクレームは躱せるし、UTR #51のドラフトで推奨されている「暗い髪色」にするよりも、非現実的な髪の色にする方が、中立的に見える*1

もうひとつ、気になっていた家族絵文字の実装の詳細が判明した*2

要は、既存の絵文字をzero width joiner (U+200D)で繋げたものを、新しい絵文字と解釈して表示している。この方法ならUnicodeに新しい絵文字を追加することなく、多様な家族構成の絵文字を実装できる*3。このやり方が、Unicode標準に取り入れられるかどうかは不明だ。

あと、新しい国旗絵文字も追加されたのだが、そのためにUnicodeのRegional Indicator Symbolsの仕様の欠陥がより明らかになった。

スウェーデンとスペインの国名コードはそれぞれSE、ESだ。ということで、スウェーデンの国旗をふたつ並べると、SESE という文字の並びになって、スウェーデンの国旗なのか、スペインの国旗なのかが曖昧だ。Twitterは、現状スペインの国旗だけに対応するので、「S[スペインの国旗]E」というように表示してしまう。

これは酷い。どうしてこうなった。UTF-16サロゲートペアを入れた時には、こういう曖昧なパターンが現れないように考慮していたじゃないか。なんでそれが絵文字で出来なかったんだ? まあ、今更愚痴を言ってもしょうがないのだが、このようなパターンに対処するための仕様を、Unicodeに入れる必要がある*4

*1:どうせなら、Androidの実装のように、人間に見えない、髪の毛のないキャラにしてしまえばいいのではないか? とも思うけど

*2:パブリック・ベータ段階で誰か調べてなかったのかしらん?

*3:4人家族より多い家族の人はどうすればいいか? それこそ沢山絵文字組み合わせて表現すりゃいいですよね

*4:互換性を考えると、Regional Indicator Symbolsの両側にzero width non-joiner (U+200C)を加えて、国旗絵文字どうしを区切るようにするのがいいだろうと思う

Emoji Skin Tone Problem

This article considers what makes Apple’s implementation of Fitzpatrick Scale Modifier problematic so that Chinese people criticize it.

(It is the abridged translation of 絵文字肌色問題 - M59のブログ.)

What makes Apple’s emoji problematic

SankeiBiz published an article to report that Chinese people criticize Apple’s implementation of the diversified skin tone emoji. The article contains a strange sentence:

公開された6種類の肌の色が並んだ写真を見ると、黄色がアジア系人種をイメージしているのは明らかで、アップルの説明はいかにも苦しい。
Judging from the published screenshot showing six skin tones, they obviously intend to describe Asian race by yellow. The excuse by Apple is farfetched.

アップル「黄色い顔文字」に中国で批判噴出 「あんな黄色い奴みたことない」「アジア人への偏見だ!」(1/3ページ) - 産経ニュース

Here, “the excuse by Apple” refers that “the yellow shade is intended to be ethnically neutral.” (Asians angered by Apple's 'racist' yellow emoji | Daily Mail Online)
Whether you agree to the excuse or not, it lacks of reasoning. Where does the concept “yellow is ethnically neutral” come from? Is it really valid?

The reason for yellow

The concept “yellow is ethnically neutral” comes from the draft of UTR #51. It writes:

People all over the world want to have emoji that reflect more human diversity, especially for skin tone. The Unicode emoji characters for people and body parts are meant to be generic, yet following the precedents set by the original Japanese carrier images, they are often shown with a light skin tone instead of a more generic (nonhuman) appearance, such as a yellow/orange color or a silhouette.

http://www.unicode.org/draft/reports/tr51/tr51.html#Diversity

When a human emoji is not immediately followed by a emoji modifier character, it should use a generic non-realistic skin tone—such as that typically used for the smiley faces—or a silhouette. Dark hair is recommended for generic images that include hair. People of every skin tone can have black (or very dark brown) hair, so it is more neutral. One exception is PERSON WITH BLOND HAIR, which needs to have blond hair regardless of skin tone.

http://www.unicode.org/draft/reports/tr51/tr51.html#Diversity

This take up the problem that some of the current emoji have too specific appearance. Unicode just specifies to be general such as happy person raising one hand or boy emoji, but they implement happy WOMAN raising one hand or WHITE boy emoji. It is too specific.
So, Design Guidelines recommends to adopt neutral appearance regarding race, ethnicity, and gender.

Emoji of Android already switched to generic one that is cartoonish or shows the contour. For example, the old boy emoji (👦 Boy Emoji) has light skin tone, while the new one shows the yellow mascot.
f:id:mandel59:20150303073112p:plain The old one is specific.
f:id:mandel59:20150303073115p:plain The new one is generic.

In short, yellow is suitable for emoji as long as it makes the emoji generic.

Specifying skin tones

The Fitzpatrick Scale Modifier in draft introduces specific emoji regarding skin tones. It is, however, hard for users to recognize that there is the distinction of generic and specific, because they are evenly presented in emoji palette or in sentences. People may receive that Apple have just added new emojis for some emojis for skin tones.

Issue in Apple’s implementation

Again, let’s see Apple’s implementation.

f:id:mandel59:20150303074243j:plain

Unlike Android, they are still human and just differ on skin tone. The leftmost one should seem to be generic, but it is just yellow.

Certainly, the figures in the draft show emoji same way:
f:id:mandel59:20150303153144p:plain A figure in 2.2 Diversity

It could be taken that “Ah, just turn the skin tone yellow, and it would be ok,” but this causes the mistake that yellow means Asians.

Besides it, Apple emoji has another problem. The emojis applied Fitzpatrick Type-3 modifier have blond hair against the draft’s recommendation. The draft recommends dark hair that people of every skin tone can be have. Blond is associated with Caucasoid, so Japanese and Chinese take Type-3 emoji as white people. Most of Japanese have Type-3 or Type-4 skin tone*1, but Type-3 emoji is not “Asian.” It is natural that they concludes the yellow one is for Asian.

Conclusion

Although there is a reason that yellow is ethnically neutral, Apple mistake the intension of yellow. Yellow does not always make emoji generic. The draft would be better to write clearly the knowledge.

絵文字肌色問題

絵文字肌色問題

Appleが、Unicode 8.0で入る見込みのFitzpatrickスケールを実装したら、デフォルトを意図していた黄色い肌色の絵文字が黄色人種だと解釈されたり、赤毛の絵文字も入れて欲しいと要望が出たりと、まあ絵文字をめぐる事態は明らかにヤバイ方向に転がりだしている。
絵文字の「肌の色」を5色から選べるようにしたアップル « WIRED.jp

黄色い肌色の絵文字の件は、SankeiBizでも記事になっている。その中に、“奇妙な”記述がある。

公開された6種類の肌の色が並んだ写真を見ると、黄色がアジア系人種をイメージしているのは明らかで、アップルの説明はいかにも苦しい。

アップル「黄色い顔文字」に中国で批判噴出 「あんな黄色い奴みたことない」「アジア人への偏見だ!」(1/3ページ) - 産経ニュース

「アップルの説明」というのは、「黄色は民族的中立(ethincally neutral)を意図したもの」というものだ。(Asians angered by Apple's 'racist' yellow emoji | Daily Mail Online) この説明で納得した人もいるだろうし、納得できないという人もいるだろう。どちらにしても、これらの記事は重要な点については伝え損ねている。それは、「黄色は民族的中立」という論がどこから出てきたのかと、その妥当性である。

黄色の根拠

Appleが「黄色は民族的中立」という説明をした根拠は、現時点でドラフトが公開されている文書、UTR #51: Unicode Emojiの、次の記述だ。

People all over the world want to have emoji that reflect more human diversity, especially for skin tone. The Unicode emoji characters for people and body parts are meant to be generic, yet following the precedents set by the original Japanese carrier images, they are often shown with a light skin tone instead of a more generic (nonhuman) appearance, such as a yellow/orange color or a silhouette.

全世界の人々が人類の多様性、特に肌の色あいについての多様性を反映した絵文字を望んでいる。Unicodeにある人々と体のパーツの絵文字は不特定的な表現であることを意図しているが、それでもオリジナルの日本のキャリアーの画像による先例の絵文字セットに従い、絵文字の肌は黄色や橙色あるいはシルエットのような、より不特定的な(人類でない)見た目ではなく、明るい色あいで表示されることがよくある。

http://www.unicode.org/draft/reports/tr51/tr51.html#Diversity

When a human emoji is not immediately followed by a emoji modifier character, it should use a generic non-realistic skin tone—such as that typically used for the smiley faces—or a silhouette. Dark hair is recommended for generic images that include hair. People of every skin tone can have black (or very dark brown) hair, so it is more neutral. One exception is PERSON WITH BLOND HAIR, which needs to have blond hair regardless of skin tone.

人間の絵文字の直後に絵文字修飾文字が続かないときは、スマイリーフェイスなどに典型的に使われているような、不特定的、非現実的な肌の色あいを使うか、シルエットを使うべきである。髪の毛を含む画像では、不特定的な画像として暗い髪色を推奨する。すべての肌の色あいの人間が黒い(あるいは濃い茶の)髪色でありうるため、それがより中立的である。例外はPERSON WITH BLOND HAIRで、この絵文字は肌の色あいに関係なくブロンドの髪であることが必要である。

http://www.unicode.org/draft/reports/tr51/tr51.html#Diversity

問題となっているのは、現行の絵文字の表現が特定的(specific)であるということだ。Unicodeの仕様では、絵文字の意味について「挙手」や「男の子」といったことしか定めていないのに、実装では「女の人の挙手」や「白人の男の子」のように、過剰に特定的な表現になっている。そこで、ドラフトの絵文字デザインガイドラインでは、用途不特定の絵文字に、人種・民族・ジェンダーに対して中立的な表現を使うよう求めている。

Androidの絵文字は、このドラフトの記述の通り、既に漫画的なキャラクターやシルエットによる不特定的な表現に移行している。例えば、男の子の絵文字(👦 Boy Emoji)は、古い絵文字では肌の色あいの薄い絵文字だったのが、新しい絵文字では人間のようではない、黄色いキャラクターによる表現になっている。不特定的な(generic)表現というのは、民族や性別を特定しないこのような表現を意味している。
f:id:mandel59:20150303073112p:plain Androidの古い絵文字、特定的(specific)表現
f:id:mandel59:20150303073115p:plain Androidの新しい絵文字、不特定的(generic)表現

肌の色あいの特定

(不特定的な表現の)絵文字の直後に、絵文字修飾文字を続けることで、その絵文字が特定の肌の色を持つことを指定できる。今回Appleが実装したのは、この仕様だ。このあたりは、文字コードについての技術的知識がないと理解が難しい。技術的には不特定的表現の絵文字と特定的表現の絵文字に差があっても、技術的知識のない利用者にとっては単にAppleが新しい絵文字を追加したようにしか見えないし、絵文字に不特定的な表現の絵文字と特定的な表現の絵文字があるということは意識しないだろう。このことも、問題の一因となっている。

Apple実装の問題点

改めて、Appleの実装を見てみよう。

f:id:mandel59:20150303074243j:plain

Androidの実装とは違い、Appleの絵文字では、不特定的な表現であるべき一番左の絵文字は、単に肌の色を黄色に変更しただけだ。
確かにドラフトに出てくる図も、単に肌の色を黄色に変更しただけの図だ。
f:id:mandel59:20150303153144p:plain 2.2 Diversityに出てくる図。

だからドラフト自体も色を黄色に変えればokであると言っているかのように読めるのだけれども、やはりただ色を変えるだけでは、事情を知らない人が不特定的な表現と特定的な表現の違いに気づくことを期待するのは難しく、黄色は黄色人種を特定的に表した絵文字だと解釈する人が出てきてもおかしくない。

また、左から3番目の、 FITZPATRICK TYPE-3 絵文字修飾文字を適用した絵文字は、ドラフトの「暗い髪色を推奨する」という記述に反し、ブロンドである。日本人はIIIとIVが多い(院長が語る「皮膚」とは ~皮膚の解剖と生理~:皮膚の色|東京 明治通りクリニック)そうだが、日本人や中国人は、まさかこのTYPE-3が自分の民族を表す絵文字だとは考えないだろう。当然、“白人”を表す絵文字だと捉えるはず*1で、そうすると(肌の色あいの薄い)日本人や中国人を表せる絵文字はないことになってしまう。だから余計に「黄色は黄色人種」という印象を強めてしまうのである。

絵文字髪色問題

もうひとつ出てきた、絵文字の髪色の問題について、現行のドラフトでは「暗い髪色がより中立的である」という記述がある。この記述は妥当だろうか。

また、すべての絵文字の髪色を変更できるようにするべきだろうか。ドラフトには、髪色や目の色、体型などといった、肌の色あい以外の多様性を表す絵文字修飾文字については、Unicodeの対処する範囲外であるとし、絵文字でなく埋め込み画像を使うなどといった、長期的な解決を望んでいる。それならば、なぜ肌の色あいだけ特別扱いするのか、という点については、はっきりしない。

また、すでにブロンドを表す絵文字があるから、赤毛の絵文字も増やすべきだという議論もできる。

これらの点について、さらに議論される必要があるだろう。

まとめ

Appleの説明する「黄色は民族的中立」というのは、無根拠な言い訳ではないのだけれども、その理屈をちゃんと理解すると、Appleの実装がドラフト仕様の意味を汲み取れておらず、実際酷い実装であることが分かる。また現行のドラフトも問題の解決に十分ではなく、さらなる改善が必要である。

Appleが出してきた実装にただ漠然とした不満をぶつけ、声の大きさで物事を変えようとするのでは、問題は解決しないだろう。そうではなく、本当の問題点を皆が適切に認識し、議論することができれば、問題を解決に向かわせることができるはずである。

付録: 雛人形 🎎 の肌色は?

今日は雛祭りなので、ついでに、雛人形の絵文字の話を書こう。

f:id:mandel59:20150303060558p:plain
これは Apple Color Emoji の雛人形だ。拡大してみると、コレジャナイ感が漂う。EmojipediaやiEmojiで、他のフォントでの雛人形を確認して欲しい。

🎎 Japanese Dolls Emoji
🎎 Japanese Dolls Emoji (U+1F38E/U+E438)

Android/Hangouts, LG Emoji, Samsung Emojiは雛人形っぽい。Twitter絵文字、これは雛人形じゃないだろと感じる。
Draft Unicode Technical Report #51 Unicode Emoji のドラフトのリスト: Draft Emoji Data (Full)にも絵文字の画像が載っている。
f:id:mandel59:20150303062221p:plain

雛人形は人間でないが、人間を象ったものだ。肌の色はどうするべきだろうか? ちなみに、ほとんどの雛人形の肌は白い。雛人形の肌は白であるべきだと、絵文字デザイナーはどのように知ればいいのだろうか? 雛人形 - Google 検索

*1:追記: そもそもFitzpatrickスケールは日焼けに対する反応による分類であって、人種の分類ではないから、コーカソイド(いわゆる“白人”)でもTYPE-3や、もっと肌の色あいの濃い人間というのも当然いる。しかし、ブロンドにしたせいで、絵文字が過剰にコーカソイド的になってしまっている。

辞書になく、ググっても出ない言葉: 単話

「単話」という言葉は辞書になく*1、ググっても出ない*2。しかし、実際使われている。「単話」は、電子コミックやドラマなどの販売形態を表すのに使われる言葉で、1話単位で販売すること、また販売された作品のことだ。曲で言えばシングル、単曲に相当する。

DMM.comの商品から、「単話」をキーワードに検索をしてみる(DMM.com 単話の検索結果)と、32件が該当する。その上、成人作品でさらに3054件該当している。

f:id:mandel59:20150225065506p:plain
f:id:mandel59:20150225065555p:plain

DMMの成人向け電子コミックのページでは、メニューからすでに「単話」が存在している。
f:id:mandel59:20150225064841p:plain

そもそもDMM独自の用語ではないのかという疑念があるので、ニコニコ静画でも検索してみると(キーワードで電子書籍を検索 単話 - ニコニコ静画)、3件に該当する(成人作品では90件該当)。Renta(Renta! - 商品一覧 - 単話)だと22件。DMMの場合は単話の形態で販売されているコミックには商品に「単話」というタグが設定されているのに対して、Rentaでは「短編・バラ売り」というタグが設定されている。しかし、「単話」という言葉自体は、DMM以外の場所でも使われることがあるようだ。

もちろんコミックだけでなく、ドラマやアニメのような物も、1話単位で販売するということがあるわけで、「単話」という言葉で表現されうる。

現在ニコニコチャンネルで配信しております「DOG DAYS」について、単話およびパックの販売価格を変更させていただきます。

http://ch.nicovideo.jp/ch60022

またDMMからの例になるのだけれども、ドラマをパック作品・単話作品に分けて販売している。DMM.com [台湾ドラマ「緑のシンフォニー~緑光森林~」【TBSオンデマンド】 第1話~第12話] TBSオンデマンド動画

*1:手元の辞書には載っていなかったというだけで、ちゃんと色々な辞書を調べたわけではない。載っている辞書があるかもしれない。

*2:Googleで検索すると出ない、というか、なぜか「単回」が出てくる。Bingなら、ちゃんと「単話」の検索結果が出る。また、「アニメ 単話」のように複数キーワードにしたり、「単話作品」で検索すると、Googleでも出てくるようになる。

「Haskellでの合成可能なオブジェクトの構成とその応用」評

Haskellでの合成可能なオブジェクトの構成とその応用では、オブジェクトをメッセージをアクションに写すものとして捉え、構成している。この構成方法では、アクションを対象、オブジェクトを射とする*1圏ができ、継承やメソッド・オーバーライドといった操作を、射の合成として表すことができる。

論文では、「操作の拡張性」「データの拡張性」「振る舞いの動的性」の3点について、クラスベースOOP・代数データ型・型クラスを用いた場合と提案手法とで比較を行っている。論文での考察結果をまとめた表を次に引用する。

操作の拡張性 データの拡張性 振舞いの動的性
クラスベースOOP
代数データ型
型クラス
提案手法

型クラスで「振舞いの動的性」を実現する

しかし、型クラスでも「振舞いの動的性」は実現できるのではないだろうか。Haskellでは存在量化を使ってElfとOrcをひとつの型にまとめられるのだから、SpellがEntityを返すように定義すればいいはずだ。

Rustでも、トレイト・オブジェクトを使うことで同様のことができる。

表現問題の観点から言えば、新しいインターフェースを追加しようとすると、Entityを変更しなくてはいけないという問題は残っていると思うのだが、振舞いの動的性の問題は解決出来ている。

提案手法における「操作の拡張性」の問題点

一方で、提案手法の実装には問題がある。論文では、メッセージの和に対して次のような実装が行われていた。

instance (Elf s, Elf t) => Elf (Sum s t) where
    elf = elf @||@ elf

演算子@||@を使っているので、これは和の左右メッセージをそれぞれ左右のオブジェクトに振り分けるということだ。左右のオブジェクトは状態を共有せず、独立して動作することになるはずで、これだとSpellで左のelfがorcに変わったとしても、右のelfはそのままということになってしまう。このような挙動は目的に沿っていないはずだ。

*1:オブジェクトは対象でなく射だ。日本語だとなんてことないが、英語にするとややこしい

内包記法についての考察

発端


https://twitter.com/kagami_hr/status/552436576576602113
https://twitter.com/kagami_hr/status/552428467711926273

疑問

  • 《省略記法》は間違いやすいとしたら、その理由は何か
  • 《省略記法》は本当に誤りなのか

なぜ間違えたのか

{
A\cap B = \left\{\,x\,\middle|\,x \in A\,\right\} \cap \left\{\,x\,\middle|\,x \in B\,\right\} = \left\{\,x\,\middle|\,x \in A \wedge x \in B\,\right\}
}
しかし
{
f(A)\cap f(B) = \left\{\,f(x)\,\middle|\,x \in A\,\right\} \cap \left\{\,f(x)\,\middle|\,x \in B\,\right\} \neq \left\{\,f(x)\,\middle|\,x \in A \wedge x \in B\,\right\}
}

ここでもし《正式な内包的記法》を用いるなら

{
f(A)\cap f(B) = \left\{\,y\,\middle|\,\exists x \in A, y = f(x)\,\right\} \cap \left\{\,y\,\middle|\,\exists x \in B, y = f(x)\,\right\}
\\ = \left\{\,y\,\middle|\,\left(\exists x \in A, y = f(x)\right)\wedge\left(\exists x \in B, y = f(x)\right)\,\right\}
}

となり、間違いは起こらない。

公理と記法

素朴に考えれば{\left\{\,x\,\middle|\,P(x)\,\right\}} という記法(集合の内包的記法)は、{P(x)}が真となるような{x}を集めた集合を表す記法となるが、このような集合の作り方を許すと、パラドックスが生じてしまう。(集合論 - Wikipedia)パラドックスを避けるため、公理によって集合を得る操作を限定する。(公理的集合論 - Wikipedia)

公理系の各公理は、記法の根拠を与えることになる。例えば、空集合の公理は記法 {\emptyset} の根拠となるし、対の公理は記法 {\{x, y\}} の根拠となる。《正式な内包的記法》 {\left\{\,x \in X\,\middle|\, P(x)\,\right\}} は、分出公理が根拠となっている。この時、縦棒の左側にある {x \in X} は、《正式な内包的記法》の一部であって命題ではない。

分出公理の代わりに、置換公理を公理とすることができる。置換公理を根拠として {\left\{\,f(x)\,\middle|\,x \in X\,\right\}} という《別の内包的記法》を定義する。この時、縦棒の右側にある {x \in X} は、この《別の内包的記法》の一部であって命題ではない。《別の内包的記法》は置換公理が根拠となっている記法であるから、《正式な内包的記法》の省略記法になっているわけではない。

《正式な内包的記法》を《別の内包的記法》を使って定義することもできる。

{
\left\{\,x \in X\,\middle|\, P(x)\,\right\} := \bigcup\left\{\,f(x)\,\middle|\,x \in X\,\right\}} ここで {
f(x) = \begin{cases}
  \{x\} & \text{if $P(x)$} \\
  \emptyset & \text{otherwise}
\end{cases}
}

内包的記法が2つあるのは面倒なので、1つにまとめた記法があると便利だ。《別の内包的記法》は、Haskellのリスト内包記法と同じ書き方になっているので、モナド内包記法の構築方法で拡張できる。

{
\left\{\,f(x, y)\,\middle|\, x \in X, y \in Y(x)\,\right\} := \bigcup\left\{\,\left\{\,f(x, y)\,\middle|\,y\in Y(x)\,\right\}\,\middle|\,x \in X\,\right\}}

適宜組み合わせて {\left\{\,f(x)\,\middle|\, x \in X, P(x)\right\}} のような記法も、意味を定義できる。