Commits

Shingo Omura committed 51aa292

The Typeclassopedia is translated to Japanese for Scala users in Japan.

Comments (0)

Files changed (1)

+<!DOCTYPE html>
+<!--[if lt IE 7]> <html class="no-js ie6" lang="en"> <![endif]-->
+<!--[if IE 7]>    <html class="no-js ie7" lang="en"> <![endif]-->
+<!--[if IE 8]>    <html class="no-js ie8" lang="en"> <![endif]-->
+<!--[if gt IE 8]><!-->  <html class="no-js" lang="en"> <!--<![endif]-->
+<head>
+	<meta charset="utf-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+
+	<title>型クラスペディア(The Typeclassopedia)</title>
+
+	<meta name="description" content="The Typeclassopedia">
+	<meta name="viewport" content="width=1024, user-scalable=no">
+
+    <!-- fonts -->
+    <link rel='stylesheet' href='http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic,700italic|PT+Sans+Narrow:400,700|Ubuntu+Mono:400,700' type='text/css'>
+
+	<!-- deck.js -->
+	<link rel="stylesheet" href="core/deck.core.css">
+	<link rel="stylesheet" href="extensions/goto/deck.goto.css">
+	<link rel="stylesheet" href="extensions/menu/deck.menu.css">
+	<link rel="stylesheet" href="extensions/status/deck.status.css">
+	<link rel="stylesheet" href="extensions/hash/deck.hash.css">
+	<link rel="stylesheet" id="transition-theme-link" href="themes/transition/fade.css">
+	<link rel="stylesheet" id="style-theme-link" href="atlassian.css">
+	<script src="jquery-1.7.min.js"></script>
+	<script src="modernizr.custom.js"></script>
+	<script src="core/deck.core.js"></script>
+	<script src="extensions/hash/deck.hash.js"></script>
+	<script src="extensions/menu/deck.menu.js"></script>
+	<script src="extensions/goto/deck.goto.js"></script>
+	<script src="extensions/status/deck.status.js"></script>
+
+	<!-- highlight.js -->
+	<link rel="stylesheet" href="solarized_light.css">
+	<script src="highlight.pack.js"></script>
+
+	<script>
+	$(document).ready(function() {
+		$.deck('.slide');
+		$('pre').each(function(i, e) {
+			hljs.highlightBlock(e, '  ');
+		});
+		$('code').each(function(i, e) {
+			hljs.highlightBlock(e);
+		});
+	});
+	</script>
+
+</head>
+
+<body class="deck-container">
+
+<p class="deck-status">slide <span class="deck-status-current"></span> / <span class="deck-status-total"></span></p>
+
+<form action="." method="get" class="goto-form">
+	<label for="goto-slide">Go to slide:</label>
+	<input type="text" name="slidenum" id="goto-slide" list="goto-datalist">
+	<datalist id="goto-datalist"></datalist>
+	<input type="submit" value="Go">
+</form>
+
+<section class="slide" style="font-size: 100%">
+	<h1>
+    <div>型クラスペディア<br/>(The Typeclassopedia)</div>
+  	<div style="font-size: 50%">John Kodumal, Atlassian</div>
+  	<div style="font-size: 50%">jkodumal@atlassian</div>
+	<div style="font-size: 25%">&nbsp;</div>
+	<div style="font-size: 25%">翻訳: 大村伸吾</div>
+        <div style="font-size: 25%">everpeace@gmail.com</div>
+  </h1>
+</section>
+
+
+<section class="slide">
+	<h2>型クラス:開世界のインターフェース</h2>
+	<p style="font-size: 60%">*訳注:開世界の原語は"Open-world"。</p>
+	<div class="slide">
+		<p>型クラスは、Javaのインターフェースに似ていますが、より柔軟です。</p>
+	</div>
+	<div class="slide">
+		<p>Scalaではtraitを使って宣言します:</p>
+<pre class="scala">
+trait Show[A] {
+	def shows(a: A): String
+}
+</pre>	
+		<p>"インターフェース"をmix-inするスタイルとは微妙に違うことに注意してください:</p>
+<pre class="scala">
+trait Show {
+	def shows(): String
+}	
+</pre>
+	</div>		
+	<div class="slide">
+		<p>型クラスに型を追加するにはこうします:</p>
+<pre class="scala">
+implicit val IntShow = new Show[Int] {
+	def shows(a: Int) = a.toString
+}
+</pre>
+</section>
+
+<section class="slide">
+	<h2>型クラスを使う</h2>
+	<div class="slide">
+		<p>Scalaのimplicitを使います:</p>
+<pre>
+def shows[A](a : A)(implicit shower: Show[A]) = shower.shows(a)
+</pre>
+	</div>
+	<div class="slide">
+		<p>もしくは<em>コンテキストバウンド</em>を使います:</p>
+<pre class="scala">
+def shows[A : Show](a : A) = implicitly[Show[A]].shows(a)
+</pre>
+		<p>(implicitly は predef で定義されています: <code>def implicitly[A](implicit a : A) = a</code>)</p>
+	</div>
+	<div class="slide">
+		<p>Scalaz は典型的な型クラスをpimpしてくれているので、こうするだけで出来ます:</p>
+<pre class="scala">
+3.shows // スコープ中に"Show[Int]"インスタンスが必要です。さもなくば型チェックに失敗します。
+</pre>
+	</div>	
+</section>
+
+<section class="slide">
+	<h2>開世界仮説</h2>
+	<p>何が得られる?</p>
+	<ul>
+		<div class="slide">
+			<li>型クラスのインスタンスを、その型自身の<em>外側</em>で定義できます。</li>
+			<ul>
+				<li> <code>Int</code> は <code>Show</code> について知らないのです。
+			</ul>
+		</div>
+		<li class="slide">これが <em>開世界仮説</em> です。</li>
+		<div class="slide">
+			<li>Scalaでは、型クラスインスタンスをスコープ内に定義することで<em>override</em> できます:
+<pre class="scala">
+def unaryShows(x : Int) : String = { 
+	implicit val AltIntShow = new Show[Int] {
+		def shows(i : Int) = (1 to i) map(_ => "|") mkString
+	}
+	shows(x)
+}
+println shows(5)      // prints '5'
+println unaryShows(5) // prints '|||||'	
+</pre>
+		</div>
+	</ul>
+</section>
+<section class="slide">
+	<h2><span style="font-size:80%;">型クラス<code>/==</code>サブタイプポリモーフィズム</span></h2>
+	<p>Scalaの型クラスで<em>できない</em>こと(<a href="https://gist.github.com/2026129">少なくとも簡単ではない</a>):
+<pre class="java">
+interface Show {
+	String show();
+}
+
+class Foo extends Show {
+	public String show() {
+		return "a foo";
+	}
+}
+
+class Bar extends Show {
+	public String show() {
+		return "a bar";
+	}
+}
+
+List[Show] showList = new ArrayList(new Foo(), new Bar(), new Foo());
+
+for (String s : showList) {
+	System.out.println(s.show);
+}
+</pre> 
+</section>
+
+<section class="slide">
+	<h2>型クラスペディア(The Typeclassopedia)</h2>
+	<img src="images/typeclassopedia.png" style="float: right; width: 100%; margin-left: 20px;">
+	<p>この型クラス階層は関数型のコードにおいて大変有用であることが証明されています:
+	<ul class="slide">
+		<li class="slide"><em>関数型デザインパターン</em></li>
+		<li class="slide">型クラスには不思議なトリックのようなものはほとんどありません</li>
+		<li class="slide">Scalaではscalaz (scala-zedと発音)というライブラリが提供してくれています</li>
+		<li class="slide">私たちは、githubにホストされているscalaz-sevenというスナップショットを使っています</li>
+		<li class="slide">この階層はHaskellで定義されているものです--- が、完璧ではありません</li>
+	</ul>
+	<p class="slide">ここではファンクタ(Functor)、Applicativeファンクタ、モナド(Monad)を扱います。</p>
+	<p class="slide" style="font-size: 60%">*<code>for</code>-comprehensionとモナドの関係も扱います。</p>
+</section>
+
+<section class="slide">
+	<h2>ファンクタ(Functor)</h2>
+	<p style="font-size: 60%">*訳注:ファンクタは関手とも呼ばれます。</p>
+	<div class="slide">
+	<p>ファンクタとは、単に「写像できる何か」のことで、次の一個のメソッドで定義されます:</p>
+<pre class="scala">
+trait Functor[F[_]] {
+	def map[A,B](fa: F[A])(f: A => B) : F[B]
+}
+</pre>
+	</div>
+	<div class="slide">
+		<p><code>Option</code>型に対するのファンクタのインスタンスは次のように定義されます:</p>
+<pre class="scala">
+implicit val OptionFunctor = new Functor[Option] {
+	def map[A, B](fa: Option[A])(f: A => B) : Option[B] = 
+		fa match {
+			case Some(a) => Some(f(a))
+			case None => None
+		}
+}
+</pre>
+	</div>
+	<div class="slide">
+		<p>Haskellでは、引数が逆になります:</p>
+<pre class="haskell">
+class Functor f where  
+    fmap :: (a -> b) -> f a -> f b	
+</pre>
+	</div>
+	<div class="slide">
+		<p>Haskell版を見ると、<code>f</code> がファンクタのコンテキストに<em>持ち上げられている(lifted)</em>のがわかります。</p>
+	</div>
+</section>
+
+<section class="slide">
+	<h2>ファンクタとしての関数の楽しみ</h2>
+	<p>"写像できるもの" から自明な例が導かれます:</p>
+	<ul>
+		<li class="slide">リスト</li>
+		<li class="slide">ツリー</li>
+		<li class="slide">マップ</li>
+	</ul>
+	<div class="slide">
+		<p>自明でない例を見てみましょう: 関数です!</p>
+<pre>
+implicit def FunctionFunctor[R] = new Functor[({type l[a] = R=>a})#l] {
+	def map[A, B](fa: R => A)(f: A => B) : R => B = (x => f(fa(x)))
+}
+</pre>
+	</div>
+	<h6 class="slide">クイズ: すこし変わった方法でmapを定義しましたが、これが表現している単純な概念とは何でしょう?</h6>
+	<div class="slide">
+	  <p>余談: ここが"ボックス"のアナロジーが壊れ始めるところです。そして、「計算のコンテキスト」という曖昧な言葉を使い始めることになるのです。</p>
+	  <p style="font-size:60%">*訳注:日本では"ボックス"ではなく"コンテナ"というアナロジーが使われることが多い。</p>
+	</div>
+</section>
+
+<section class="slide">
+	<h2>ファンクタの法則</h2>
+	<p>ファンクタには、ファンクタが"正しく振る舞える"ようにするための、いくつかの制約が存在します:</p>
+	<ul>
+		<div class="slide">
+			<li><code>map(fa)(id) === fa</code></li> (恒等関数の写像先は恒等関数であること)
+		</div>
+		<div class="slide">	
+			<li><code>map(fa)(f compose g) === map(map(fa)(g))(f)</code></li> (合成関数の写像先は、各関数を写像した関数を合成であること)
+		</div>
+	</ul>
+	<p class="slide">これらの法則は、馬鹿げた<code>map</code>の定義を回避するもので、渡された関数がどう振る舞うか予測できるようにしています。</p>
+	<p class="slide">これらの法則は、型システムでは保証<strong>できない</strong>ことに注意してください。
+</section>
+
+<section class="slide">
+	<h2>余談: パラメトリシティ</h2>
+	<blockquote class="slide">
+		<p>大きな弱みは大きな力を生み出す。(With great weakness comes great power...)</p>
+		<cite>Ben "Pierce" Parker</cite>
+	</blockquote>
+	<blockquote class="slide">
+		<p>多くの力は多くの問題を生み出す。(Mo' power, mo' problems...)</p>
+		<cite>Biggie Smalls</cite>
+	</blockquote>
+	<div class="slide">
+<pre class="scala">
+def fun[A](a : A) : A = ...
+</pre>
+	<p><code>fun</code>って何?</p>
+	</div>
+	<div class="slide">
+<pre class="scala">
+val x : List[Int] = ...
+def foo[F[_] : Functor](fs : F[Int]) = ...
+</pre>
+	<p><code>foo(x).length</code>って何?<p>
+	</div>
+</section>
+
+<section class="slide">
+	<h2>Applicative ファンクタ</h2>
+	<p><code>map</code>だけでも様々なことが出来ますが、足りない時もあります。</p>
+	<div class="slide">
+		<p>次の例を考えましょう:</p>
+<pre class="scala">
+def parse(s : String) : Option[Int] = ...
+</pre>
+	</div>
+	<div class="slide">
+		<p>2つのパースされた整数を<code>map</code>を使って足してみましょう:</p>
+<pre class="scala">
+parse("3").map((x: Int) => (y: Int) =>  x + y) // ???
+</pre>
+	</div>
+	<div class="slide">
+		<p>これだと<code>Option[Int => Int]</code>という型が返ってきてしまいます。どうすればよいでしょう?
+	</div>
+	<h5 class="slide">もっと強力な<code>map</code>のような操作が必要です。</h5>
+</section>
+
+<section class="slide">
+	<h2>Applicative ファンクタ</h2>
+	<div class="slide">
+		<p>さぁ<code>Functor</code>に能力を追加しましょう:
+<pre class="scala">
+trait Applicative[F[_]] extends Functor {
+	def <*>[A, B](fa: F[A])(f : F[A => B]) : F[B]
+	// ... Applicativeにはまだ必要なものがありますが, 後で紹介します
+}
+</pre>
+	</div>
+	<div class="slide">
+		<p>これを使うと前の例はこんな風に出来るようになります:</p>
+<pre class="scala">
+(parse("3")).<*>(parse("Nope").map(x => (y : Int) => x + y))
+</pre>
+		<p style="font-size: 60%">(オェッ)</p>
+	</div>
+	<div class="slide">
+		<p>Haskellでは、もうちょっとわかりやすくなります: </p>
+<pre class="haskell">
+(+) <$> parse("3") <*> parse("Nope") 
+</pre>	
+	</div>
+	<div class="slide">
+		<p>Scalazの<code>ApplicativeBuilder</code> を使うといくらかは改善できます:</p>
+<pre class="scala">
+(parse("3") |@| parse("Nope"))(_ + _)
+</pre>
+	</div>
+</section>
+
+<section class="slide">
+	<p style="font-size: 2500%">|@|</p>
+</section>
+
+<section class="slide">
+	<img src="images/macaulay.jpg" style="float: right; width: 100%;">
+	<h3>(マコーレー・カルキン演算子)</h3>
+</section>
+
+<section class="slide">
+	<h2>Applicativeの話題をもう少し</h2>
+	<div class="slide">
+		<p>もし<code>Option</code>でない引数があったらどうする?</p>
+<pre class="scala">
+	(parse("3") |@| 4 /* だめだめ、マコーレーにはカルキンじゃなきゃ */) (_ + _)
+</pre>
+	</div>	
+	<div class="slide">
+		<p>そこで、小さな変更を加えましょう:</p>
+<pre class="scala">
+trait Applicative[F[_]] extends Functor {
+	def <*>[A, B](fa: F[A])(f : F[A => B]) : F[B]
+	<strong>def point[A](a : A): F[A]</strong>
+}
+</pre>
+	<h6 class="slide">演習: <code>Option</code>型に対するApplicativeファンクタのインスタンスを定義してください<h6>
+	</div>
+</section>
+
+<!--
+<section class="slide">
+	<p style="font-size: 2250%"><|*|></p>
+</section>
+
+<section class="slide">
+	<img src="images/mr-incredible.jpg" style="float: right; width: 100%;">
+	<h3>(Asterisks Man, Arms Akimbo)</h3>
+</section>
+-->
+
+<section class="slide">
+	<h2>モナド(Monad)のチュートリアル</h2>
+	<div class="slide">
+		<img src="images/ackbar.jpeg" style="width=100%">
+	</div>
+	<div class="slide">
+		<a href="http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/"><h4>そう。罠ですよ。</h4></a>
+	</div>
+</section>
+
+<section class="slide">
+	<h2>モナド(Monad)</h2>
+	<p>さっきと同じように、新しいタスクについて考えて、何がうまく行かないかを見てみましょう。</p>
+	<div class="slide">
+		<p>再び<code>parse</code>の例を考えます:</p>
+<pre class="scala">
+def parse(s : String) : Option[Int] = ...
+</pre>
+	</div>
+	<div class="slide">
+		<p>入力される<code>String</code>がクエリパラメータだったらどうでしょうか?
+<pre class="scala">
+val x : Option[String] = params.get("x")
+</pre>
+		<p>今、<code>Option[String]</code>型の値と<code>String => Option[Int]</code>という型の関数があります。</p>
+	</div>
+	<div class="slide">
+		<p>このとき<code>map</code>しかなかったらどうなるでしょうか。</p>
+<pre class="scala">
+x.map(parse) // Option[Option[Int]] ??
+</pre>
+	</div>	
+</section>
+
+<section class="slide">
+	<h2>モナド(Monad)</h2>
+	<div class="slide">
+		<p>さぁ<code>Applicative</code>に能力を追加しましょう:
+<pre class="scala">
+trait Monad[F[_]] extends Applicative {
+	def >>=[A, B](fa: F[A])(f : A => F[B]) : F[B]
+}
+</pre>
+	<p>これはバインド(<code>bind</code>)と発音します。</p>
+	</div>
+	<div class="slide">
+		<p>これで、先の例はこんな風に出来るようになります:</p>
+<pre class="scala">
+params.get("x") >>= parse // Option[Int]
+</pre>
+	</div>
+	<div class="slide">
+		<p>もっとweb-basedな計算機らしい例にしてみましょう:</p>
+<pre class="scala">
+params.get("x") >>= parse >>= (x => (params.get("y") >>= parse) map (_ + x) )
+</pre>
+<p style="font-size: 60%">(オェッ)</p>
+	</div>
+</section>
+
+<section class="slide">
+	<h2>救いの糖衣構文</h2>
+	<div class="slide">
+		<p>最後の例から、こんな典型的なパターンが考えられます: </p>
+<pre class="scala">
+monadicX >>= (x => monadicY >>= (y => monadicZ map (z => x+y+z))) 
+</pre>
+		<p>最後の<code>map</code>まで<code>bind</code>が入れ子になっています</p>
+	</div>
+	<div class="slide">
+		<p>少しリフォーマットしてみるとこうなります: </p>
+<pre class="scala">
+monadicX >>= (x => 
+monadicY >>= (y => 
+monadicZ map (z => 
+   x+y+z
+))) 
+</pre>
+	</div>
+	<div class="slide">
+		<p>Scalaでは<code>for</code>-comprehensionを使ってこう書けます:
+<pre class="scala">
+for {
+	x <- monadicX
+	y <- monadicY
+	z <- monadicZ
+} yield x + y + z
+</pre>
+	<p style="font-size:60%">(大分良くなった!)</p>
+	</div>
+
+</section>
+
+<section class="slide">
+	<h2>埋込み言語としてのモナド</h2>
+	<div class="slide">
+		<p>モナドのアイデアを証明するのにこの<a href="http://en.wikibooks.org/wiki/Haskell/Understanding_monads">武器</a>を紹介します。これを考えてみてください:</p>
+<pre class="scala">
+for {
+	x <- monadicX
+	y <- monadicY
+} yield x + y
+</pre>
+		<p>Q: このコードはどう動くでしょうか?</p>
+	</div>
+	<div class="slide">
+		<p>A: モナドの種類によります。</p>
+	</div>
+	<div class="slide">
+		<p>モナドを使った<code>for</code>-comprehensionは、モナドによってセマンティクスを定義される埋込みプログラミング言語と見なせます:</p>
+	</div>
+	<div class="slide">
+		<table style="width: 100%">
+			<tr>
+				<th align="left">モナド</th>
+				<th align="left">セマンティクス</th>
+			</tr>
+			<tr class="slide">
+				<td><code>Option</code></td>
+				<td>無名の例外</td>
+			</tr>
+			<tr class="slide">
+				<td><code>Reader</code></td>
+				<td>グローバルな環境</td>
+			</tr>
+			<tr class="slide">
+				<td><code>Validation</code></td>
+				<td>記述的な例外</td>
+			</tr>
+			<tr class="slide">
+				<td><code>List</code></td>
+				<td>非決定的な計算</td>
+			</tr>
+		</table>
+	</div>
+</section>
+
+</body>
+</html>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.