-
Notifications
You must be signed in to change notification settings - Fork 0
/
chatbot.html
555 lines (522 loc) · 48.2 KB
/
chatbot.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Haskellで人工無脳をつくろう — laskell 0.0.1 documentation</title>
<link rel="stylesheet" href="static/pyramid.css" type="text/css" />
<link rel="stylesheet" href="static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.0.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="static/jquery.js"></script>
<script type="text/javascript" src="static/underscore.js"></script>
<script type="text/javascript" src="static/doctools.js"></script>
<link rel="top" title="laskell 0.0.1 documentation" href="index.html" />
<link rel="next" title="HaskellでPLEAC (todo)" href="pleac.html" />
<link rel="prev" title="ゆるふわHaskell (Light & Airy Haskell)" href="index.html" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="static/ie6.css" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="pleac.html" title="HaskellでPLEAC (todo)"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="ゆるふわHaskell (Light & Airy Haskell)"
accesskey="P">previous</a> |</li>
<li><a href="index.html">laskell 0.0.1 documentation</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="haskell">
<h1>Haskellで人工無脳をつくろう<a class="headerlink" href="#haskell" title="Permalink to this headline">¶</a></h1>
<div class="section" id="id1">
<h2>はじめに<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
<p>Haskellで人工無脳をつくると面白そうなのでやってみることにしました。Twitterのボットくらいを目指します。</p>
</div>
<div class="section" id="id2">
<h2>Haskell開発環境を用意しよう<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h2>
<div class="section" id="haskell-platform">
<h3>Haskell Platformのインストール<a class="headerlink" href="#haskell-platform" title="Permalink to this headline">¶</a></h3>
<p><a class="reference external" href="http://hackage.haskell.org/platform/">Haskell Platform</a>から自分
のOSに対応するものをダウンロードしてインストールすると、<a class="reference external" href="http://lambda.haskell.org/platform/doc/current/frames.html">一通りの開発環境</a>が揃います。</p>
</div>
<div class="section" id="cabal">
<h3>cabalを使う<a class="headerlink" href="#cabal" title="Permalink to this headline">¶</a></h3>
<p>cabalは<a class="reference external" href="http://hackage.haskell.org/packages/hackage.html">Hackage</a>のパッケージをインストールするためのツールです。
これはいわゆるperlのcpanやpythonのeasy_installにあたるものなので、早めに覚えるべきコマンドです。先人の知恵を上手に取り入れて
素早く開発するのはHaskellでも一緒です。</p>
<p>Haskell Platformをインストールすれば使えるようになっているはずなので、
早速コマンド入力用のユーザーインターフェースライブラリを導入してみます</p>
<div class="highlight-sh"><div class="highlight"><pre><span class="nv">$ </span>cabal install readline
</pre></div>
</div>
<p>幾つかのログ情報が端末に出力されて、インストールは終了すると思います。簡単ですね。</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>osxユーザーでreadlineをhomebrew経由でインストールしている場合は</p>
<p>cabal install readline –configure-option=–with-readline-libraries=”/usr/local/Cellar/readline/6.2.2/lib” –configure-option=–with-readline-includes=”/usr/local/Cellar/readline/6.2.2/include”</p>
<p class="last">でインストールできるはずです。readlineのバージョンは利用しているものに適宜読み替えてください。</p>
</div>
</div>
</div>
<div class="section" id="id5">
<h2>人工無脳の名前を考えよう<a class="headerlink" href="#id5" title="Permalink to this headline">¶</a></h2>
<p>まずは人工無能の名前を考えなければいけませんよね。
なんといっても、いい名前はモチベーションに必須ですからね。</p>
<p>というわけであらかじめ考えておきました。</p>
<p>命名「モナポ(monapo)」</p>
<ul class="simple">
<li>Haskellと言えばアレ</li>
<li>地元のB級グルメ「つけナポリタン」のご当地キャラ</li>
<li>地元の選挙区出身の原発問題担当大臣問題から</li>
</ul>
<p>なかなかいい名前です。</p>
</div>
<div class="section" id="id6">
<h2>オウム返しさせる<a class="headerlink" href="#id6" title="Permalink to this headline">¶</a></h2>
<p>最初は人工無能の基本であるオウム返しをさせてみます。ちなみにうちの三歳
の息子も言ったことを繰り返すの、でちょっとめんどくさいと思う時がありま
すが、ヒトの会話の発達段階には必要なイベントなんでしょう。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="kr">import</span> <span class="nn">System.Console.Readline</span>
<span class="nf">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="nf">main</span> <span class="ow">=</span> <span class="n">loop</span>
<span class="kr">where</span> <span class="n">loop</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">maybeLine</span> <span class="ow"><-</span> <span class="n">readline</span> <span class="s">"> "</span>
<span class="kr">case</span> <span class="n">maybeLine</span> <span class="kr">of</span>
<span class="kt">Nothing</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="s">"quit"</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="n">line</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">line</span>
<span class="n">loop</span>
</pre></div>
</div>
<p>上記のコードをmonapo.hsという名前で保存したら早速コンパイルしてみましょう</p>
<div class="highlight-sh"><div class="highlight"><pre><span class="nv">$ </span>ghc --make monapo
<span class="o">[</span>1 of 1<span class="o">]</span> Compiling Main <span class="o">(</span> monapo.hs, monapo.o <span class="o">)</span>
Linking monapo ...
</pre></div>
</div>
<p>無事コンパイルできたら、早速実行してみましょう。あいさつからはじめて、
とりあえず近所の民主党候補のポスターで覚えていたものをオウム返しさせて
みます。</p>
<div class="highlight-sh"><div class="highlight"><pre><span class="nv">$ </span>./monapo
> こんにちわ
monapo> こんにちわ
> ごうしでごー
monapo> ごうしでごー
> たむけん参上!
monapo> たむけん参上!
</pre></div>
</div>
<div class="section" id="id7">
<h3>コードの説明<a class="headerlink" href="#id7" title="Permalink to this headline">¶</a></h3>
<p>まずはモジュールをインポートします。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="kr">import</span> <span class="nn">System.Console.Readline</span>
</pre></div>
</div>
<p>続いてmainの定義を書きます。</p>
<ul class="simple">
<li>mainはloopっていう関数です</li>
<li>loopっていう関数はreadlineで入力を受け付けて、入力が</li>
</ul>
<blockquote>
<div><ul class="simple">
<li>何もない場合と”quit”という文字列の場合はreturnする</li>
<li>それ以外の場合はオウム返ししてloop関数を実行する</li>
</ul>
</div></blockquote>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="nf">main</span> <span class="ow">=</span> <span class="n">loop</span>
<span class="kr">where</span> <span class="n">loop</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">maybeLine</span> <span class="ow"><-</span> <span class="n">readline</span> <span class="s">"> "</span>
<span class="kr">case</span> <span class="n">maybeLine</span> <span class="kr">of</span>
<span class="kt">Nothing</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="s">"quit"</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="n">line</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">line</span>
<span class="n">loop</span>
</pre></div>
</div>
<p>ポイントはdoです。do構文を使うと関数が順番に実行されるようになります。
よくある手続き型のスクリプト言語の感覚で書けるようになります。それがdo
です。</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">doはmoco’sキッチンにおけるオリーブオイルのようなものだと覚えておけば
安心です。怖がらずなんにでもかけてみよう!(※ただしメインに限る)</p>
</div>
<p>下の例だとputStrLnした後にloopを実行してます。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="kt">Just</span> <span class="n">line</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">line</span>
<span class="n">loop</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="id8">
<h2>ランダムに応答を返す<a class="headerlink" href="#id8" title="Permalink to this headline">¶</a></h2>
<p>オウム返しはうまくいったので、続いて予め決められた返事のリストからラン
ダムに一つ選んで返すようにしてみましょう。</p>
<div class="section" id="haskellerhoogle">
<h3>本物のHaskellerはHoogleを使う<a class="headerlink" href="#haskellerhoogle" title="Permalink to this headline">¶</a></h3>
<p>コードの戦略としては応答候補のリストを用意して、これからランダムに一つ
選択したいわけですが、Haskellでランダムを扱うにはどうすればいいのでしょう?</p>
<div class="highlight-haskell"><div class="highlight"><pre> <span class="kr">import</span> <span class="nn">System.Console.Readline</span>
<span class="n">responses</span> <span class="ow">=</span> <span class="p">[</span>
<span class="s">"ジョジョ立ちしてみて"</span><span class="p">,</span>
<span class="s">"こんにちわ"</span><span class="p">,</span>
<span class="s">"すごいHaskellたのしく学んでますか?"</span><span class="p">]</span>
<span class="n">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="n">main</span> <span class="ow">=</span> <span class="n">loop</span>
<span class="kr">where</span> <span class="n">loop</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">maybeLine</span> <span class="ow"><-</span> <span class="n">readline</span> <span class="s">"> "</span>
<span class="kr">case</span> <span class="n">maybeLine</span> <span class="kr">of</span>
<span class="kt">Nothing</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="s">"quit"</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="n">line</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="hll"> <span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="c1">-- responseをどうやって選択するのか?</span>
</span> <span class="n">loop</span>
</pre></div>
</div>
<p>そんな時は<a class="reference external" href="http://www.haskell.org/hoogle/">Hoogle</a>で検索してみま
しょう。randomというキーワードで検索すると<a class="reference external" href="http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html">System.Random</a>がヒットするはずです。これは求めるものに近そうなのできちんと見ていきます。</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">cabal install でhoogleをインストールするとCUIで検索できるようになって便利なので入れておきましょう</p>
</div>
<p>randomパッケージの中から出力の型がIO [何か]というものを探します。なぜIOがついているものを探すかというとmain関数の型の定義が</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span>
</pre></div>
</div>
<p>となっているからです。<strong>IOというラベルの張っている型はIOというラベル
の張っている型を出力する関数じゃないとつなげることができない</strong>と覚え
ておけばいいでしょう。そんな感じで見ていくとgetStdRandomというものが見
つかりました。確認のために型を見てみると</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">getStdRandom</span> <span class="ow">::</span> <span class="p">(</span><span class="kt">StdGen</span> <span class="ow">-></span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="kt">StdGen</span><span class="p">))</span> <span class="ow">-></span> <span class="kt">IO</span> <span class="n">a</span>
</pre></div>
</div>
<p>となっています。StdGenとは一体何だ?理解するのに大変な予感がするんだ
が、、、、と気になるところですが、すぐ後ろに簡単な使い方が載っているの
で見てみると、</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">rollDice</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">rollDice</span> <span class="ow">=</span> <span class="n">getStdRandom</span> <span class="p">(</span><span class="n">randomR</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">6</span><span class="p">))</span>
</pre></div>
</div>
<p>ズバリな感じで、指定した範囲の数字をランダムに出力する関数みたいです。
これをちょっとモディファイすれば使えそうです。というわけで結局StdGenを
深追いしなくて良くなりましたね。あとはうまく貼りあわせればいいだけなの
で出来上がったコードを載せておきます。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="kr">import</span> <span class="nn">System.Console.Readline</span>
<span class="kr">import</span> <span class="nn">System.Random</span>
<span class="nf">randomNumGen</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">randomNumGen</span> <span class="ow">=</span> <span class="n">getStdRandom</span> <span class="p">(</span><span class="n">randomR</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">(</span><span class="n">length</span> <span class="n">response</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="nf">response</span> <span class="ow">=</span> <span class="p">[</span>
<span class="s">"ジョジョ立ちしてみて"</span><span class="p">,</span>
<span class="s">"こんにちわ"</span><span class="p">,</span>
<span class="s">"すごいHaskellたのしく学んでますか?"</span><span class="p">]</span>
<span class="nf">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="nf">main</span> <span class="ow">=</span> <span class="n">loop</span>
<span class="kr">where</span> <span class="n">loop</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">maybeLine</span> <span class="ow"><-</span> <span class="n">readline</span> <span class="s">"> "</span>
<span class="kr">case</span> <span class="n">maybeLine</span> <span class="kr">of</span>
<span class="kt">Nothing</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="s">"quit"</span> <span class="ow">-></span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="n">line</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">index</span> <span class="ow"><-</span> <span class="n">randomNumGen</span>
<span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">response</span> <span class="o">!!</span> <span class="n">index</span>
<span class="n">loop</span>
</pre></div>
</div>
</div>
<div class="section" id="id9">
<h3>コードの説明<a class="headerlink" href="#id9" title="Permalink to this headline">¶</a></h3>
<p>responseでリストを定義してrandomNumGenでリストのインデックスの整数値が
ランダムに選ばれるようにしています。(関数の型がIO Intであることに気がつ
いてください)。あとはmain関数中で、ランダムに選ばれたindex値を用いて
responseの中から応答すべき文字列を選択しています。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">index</span> <span class="ow"><-</span> <span class="n">randomNumGen</span>
<span class="nf">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">response</span> <span class="o">!!</span> <span class="n">index</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="id10">
<h2>感情モデルの作成<a class="headerlink" href="#id10" title="Permalink to this headline">¶</a></h2>
<div class="section" id="id11">
<h3>全体の流れ<a class="headerlink" href="#id11" title="Permalink to this headline">¶</a></h3>
<p>応答をランダムに返す人工無能ができたところで、応答の選び方をちょっと工
夫したくなりますよね?</p>
<p>例えば整数値を</p>
<ul class="simple">
<li>1:ハッピー (両手で大きくハートを描いた後、手をハートの形に組んで光波を放ち、敵に直撃させて浄化するテンション)</li>
<li>0:ノーマル</li>
<li>-1:ネガティブ (白紙の未来を黒く塗りつぶす感じで)</li>
</ul>
<p>という心理状態に見立てて、それぞれの値に応じたレスポンスを返すようにするのはどうでしょう?</p>
<p>先ほどのresponseに関しては</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">response</span> <span class="ow">=</span> <span class="p">[</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"ピースソーグーーッド!"</span><span class="p">),</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"ウルトラハッピー"</span><span class="p">),</span>
<span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s">"こんにちわ"</span><span class="p">),</span>
<span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s">"すごいHaskellたのしく学んでますか?"</span><span class="p">),</span>
<span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s">"お前それサバンナでも同じ事言えんの?"</span><span class="p">),</span>
<span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s">"小町とHagexみすぎだろ"</span><span class="p">)]</span>
</pre></div>
</div>
<p>といった感じの定義を用意しておいて、(1,0,-1)の応答を返すようにfilter関
数でフィルターすればいいですね。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">map</span> <span class="n">snd</span> <span class="o">$</span> <span class="n">filter</span> <span class="p">(</span><span class="nf">\</span><span class="n">s</span> <span class="ow">-></span> <span class="n">fst</span> <span class="n">s</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="n">response</span> <span class="c1">-- タプルの最初が1である応答のリストを返す</span>
</pre></div>
</div>
<p>こんな感じで選ばれた応答リストをランダムに返せばよさそうです。</p>
</div>
<div class="section" id="id12">
<h3>ロボット生命体的なアイテムの登場です<a class="headerlink" href="#id12" title="Permalink to this headline">¶</a></h3>
<p>続いて、monapoに心理状態を覚えさせることを考えます。ほめられたら1増やし
、けなされたら1減らすことにします。</p>
<p>IO ()にはStateTっていうプラグインみたいな感覚で付けられる型があるため、
それを使うとなぜか状態が扱えます。TはTransformerの頭文字で、ロボット生
命体のアレと一緒です。彼らも合体してより強くなるのでそれのイメージで理
解しておけば大丈夫です。</p>
<p>StateTを利用すると、doのなかでset,putが使えるようになります。これはま
るでデータベースのAPIを操作している感覚でデータの出し入れが行えるように
なるので、なんというかお手軽です。</p>
<p>他に、心理状態がIntなのはコードリーディング的に問題あるだろうという私の
特別なはからいによりEmotionという別名を付けておきました。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="kr">type</span> <span class="kt">Emotion</span> <span class="ow">=</span> <span class="kt">Int</span>
<span class="nf">happ</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">happ</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">get</span>
<span class="kr">if</span> <span class="n">em</span><span class="o">+</span><span class="mi">1</span> <span class="o">></span> <span class="mi">1</span> <span class="kr">then</span> <span class="kr">do</span> <span class="n">put</span> <span class="mi">1</span> <span class="o">>></span> <span class="n">return</span> <span class="mi">1</span>
<span class="kr">else</span> <span class="kr">do</span> <span class="n">put</span> <span class="p">(</span><span class="n">em</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">>></span> <span class="n">return</span> <span class="p">(</span><span class="n">em</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="nf">sad</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">sad</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">get</span>
<span class="kr">if</span> <span class="p">(</span><span class="n">em</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="kr">then</span> <span class="kr">do</span> <span class="n">put</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">>></span> <span class="n">return</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="kr">else</span> <span class="kr">do</span> <span class="n">put</span> <span class="p">(</span><span class="n">em</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">>></span> <span class="n">return</span> <span class="p">(</span><span class="n">em</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="nf">keep</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">keep</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">get</span>
<span class="n">return</span> <span class="n">em</span>
</pre></div>
</div>
<p>ここで、happは幸せ関数、sadは不幸せ関数、keepはkeep calmです。大したこ
とやってないので説明は端折ります。</p>
<p>ランダムに選択する部分もindexを返すんじゃなく直接応答を選択するように
ちょっと変えておきます</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">randomNumGen</span> <span class="ow">::</span> <span class="kt">Int</span> <span class="ow">-></span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">randomNumGen</span> <span class="n">n</span> <span class="ow">=</span> <span class="n">getStdRandom</span> <span class="p">(</span><span class="n">randomR</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="nf">choiceResponse</span> <span class="ow">::</span> <span class="p">[</span><span class="kt">String</span><span class="p">]</span><span class="ow">-></span> <span class="kt">IO</span> <span class="kt">String</span>
<span class="nf">choiceResponse</span> <span class="n">cs</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">index</span> <span class="ow"><-</span> <span class="n">randomNumGen</span> <span class="o">$</span> <span class="n">length</span> <span class="n">cs</span>
<span class="n">return</span> <span class="p">(</span><span class="n">cs</span> <span class="o">!!</span> <span class="n">index</span><span class="p">)</span>
</pre></div>
</div>
<p>ちょっとめんどくさいのはmainですが、もとのコードにStateT対応させるため
にliftとliftIOをかさねているだけです。入力でfacebookライクにいいね!されると幸
福度が増して、逆にダメ出しされると幸福度が下がるようにしてみました。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="nf">code</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="nf">code</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">loop</span>
<span class="kr">where</span> <span class="n">loop</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">maybeLine</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">readline</span> <span class="s">"> "</span>
<span class="kr">case</span> <span class="n">maybeLine</span> <span class="kr">of</span>
<span class="kt">Nothing</span> <span class="ow">-></span> <span class="kr">do</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="s">"quit"</span> <span class="ow">-></span> <span class="kr">do</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="n">line</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="kr">case</span> <span class="n">line</span> <span class="kr">of</span>
<span class="s">"いいね"</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">happ</span>
<span class="n">choiced</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">choiceResponse</span> <span class="o">$</span> <span class="n">map</span> <span class="n">snd</span> <span class="o">$</span> <span class="n">filter</span> <span class="p">(</span><span class="nf">\</span><span class="n">s</span> <span class="ow">-></span> <span class="n">fst</span> <span class="n">s</span> <span class="o">==</span> <span class="n">em</span><span class="p">)</span> <span class="n">responses</span>
<span class="n">liftIO</span> <span class="o">$</span> <span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">choiced</span>
<span class="s">"だめだね"</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">sad</span>
<span class="n">choiced</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">choiceResponse</span> <span class="o">$</span> <span class="n">map</span> <span class="n">snd</span> <span class="o">$</span> <span class="n">filter</span> <span class="p">(</span><span class="nf">\</span><span class="n">s</span> <span class="ow">-></span> <span class="n">fst</span> <span class="n">s</span> <span class="o">==</span> <span class="n">em</span><span class="p">)</span> <span class="n">responses</span>
<span class="n">liftIO</span> <span class="o">$</span> <span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">choiced</span>
<span class="n">otherwise</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">keep</span>
<span class="n">choiced</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">choiceResponse</span> <span class="o">$</span> <span class="n">map</span> <span class="n">snd</span> <span class="o">$</span> <span class="n">filter</span> <span class="p">(</span><span class="nf">\</span><span class="n">s</span> <span class="ow">-></span> <span class="n">fst</span> <span class="n">s</span> <span class="o">==</span> <span class="n">em</span><span class="p">)</span> <span class="n">responses</span>
<span class="n">liftIO</span> <span class="o">$</span> <span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">choiced</span>
<span class="n">loop</span>
<span class="nf">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="nf">main</span> <span class="ow">=</span> <span class="n">runStateT</span> <span class="n">code</span> <span class="mi">0</span> <span class="o">>></span> <span class="n">return</span> <span class="nb">()</span>
</pre></div>
</div>
</div>
<div class="section" id="id13">
<h3>全コード<a class="headerlink" href="#id13" title="Permalink to this headline">¶</a></h3>
<p>全部のコードを載せておきます。</p>
<div class="highlight-haskell"><div class="highlight"><pre><span class="kr">import</span> <span class="nn">Control.Monad.State</span>
<span class="kr">import</span> <span class="nn">System.Console.Readline</span>
<span class="kr">import</span> <span class="nn">System.Random</span>
<span class="nf">randomNumGen</span> <span class="ow">::</span> <span class="kt">Int</span> <span class="ow">-></span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">randomNumGen</span> <span class="n">n</span> <span class="ow">=</span> <span class="n">getStdRandom</span> <span class="p">(</span><span class="n">randomR</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="nf">choiceResponse</span> <span class="ow">::</span> <span class="p">[</span><span class="kt">String</span><span class="p">]</span><span class="ow">-></span> <span class="kt">IO</span> <span class="kt">String</span>
<span class="nf">choiceResponse</span> <span class="n">cs</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">index</span> <span class="ow"><-</span> <span class="n">randomNumGen</span> <span class="o">$</span> <span class="n">length</span> <span class="n">cs</span>
<span class="n">return</span> <span class="p">(</span><span class="n">cs</span> <span class="o">!!</span> <span class="n">index</span><span class="p">)</span>
<span class="nf">responses</span> <span class="ow">=</span> <span class="p">[</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"ピースソーグーーッド!"</span><span class="p">),</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"ウルトラハッピー"</span><span class="p">),</span>
<span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s">"こんにちわ"</span><span class="p">),</span>
<span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s">"すごいHaskellたのしく学んでますか?"</span><span class="p">),</span>
<span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s">"お前それサバンナでも同じ事言えんの?"</span><span class="p">),</span>
<span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s">"小町とHagexみすぎだろ"</span><span class="p">)]</span>
<span class="kr">type</span> <span class="kt">Emotion</span> <span class="ow">=</span> <span class="kt">Int</span>
<span class="nf">happ</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">happ</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">get</span>
<span class="kr">if</span> <span class="n">em</span><span class="o">+</span><span class="mi">1</span> <span class="o">></span> <span class="mi">1</span> <span class="kr">then</span> <span class="kr">do</span> <span class="n">put</span> <span class="mi">1</span> <span class="o">>></span> <span class="n">return</span> <span class="mi">1</span>
<span class="kr">else</span> <span class="kr">do</span> <span class="n">put</span> <span class="p">(</span><span class="n">em</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">>></span> <span class="n">return</span> <span class="p">(</span><span class="n">em</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="nf">sad</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">sad</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">get</span>
<span class="kr">if</span> <span class="p">(</span><span class="n">em</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="kr">then</span> <span class="kr">do</span> <span class="n">put</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">>></span> <span class="n">return</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="kr">else</span> <span class="kr">do</span> <span class="n">put</span> <span class="p">(</span><span class="n">em</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">>></span> <span class="n">return</span> <span class="p">(</span><span class="n">em</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="nf">keep</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="kt">Int</span>
<span class="nf">keep</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">get</span>
<span class="n">return</span> <span class="n">em</span>
<span class="nf">code</span> <span class="ow">::</span> <span class="kt">StateT</span> <span class="kt">Emotion</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="nf">code</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">loop</span>
<span class="kr">where</span> <span class="n">loop</span> <span class="ow">=</span> <span class="kr">do</span>
<span class="n">maybeLine</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">readline</span> <span class="s">"> "</span>
<span class="kr">case</span> <span class="n">maybeLine</span> <span class="kr">of</span>
<span class="kt">Nothing</span> <span class="ow">-></span> <span class="kr">do</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="s">"quit"</span> <span class="ow">-></span> <span class="kr">do</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">return</span> <span class="nb">()</span>
<span class="kt">Just</span> <span class="n">line</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="kr">case</span> <span class="n">line</span> <span class="kr">of</span>
<span class="s">"いいね"</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">happ</span>
<span class="n">choiced</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">choiceResponse</span> <span class="o">$</span> <span class="n">map</span> <span class="n">snd</span> <span class="o">$</span> <span class="n">filter</span> <span class="p">(</span><span class="nf">\</span><span class="n">s</span> <span class="ow">-></span> <span class="n">fst</span> <span class="n">s</span> <span class="o">==</span> <span class="n">em</span><span class="p">)</span> <span class="n">responses</span>
<span class="n">liftIO</span> <span class="o">$</span> <span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">choiced</span>
<span class="s">"だめだね"</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">sad</span>
<span class="n">choiced</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">choiceResponse</span> <span class="o">$</span> <span class="n">map</span> <span class="n">snd</span> <span class="o">$</span> <span class="n">filter</span> <span class="p">(</span><span class="nf">\</span><span class="n">s</span> <span class="ow">-></span> <span class="n">fst</span> <span class="n">s</span> <span class="o">==</span> <span class="n">em</span><span class="p">)</span> <span class="n">responses</span>
<span class="n">liftIO</span> <span class="o">$</span> <span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">choiced</span>
<span class="n">otherwise</span> <span class="ow">-></span> <span class="kr">do</span>
<span class="n">em</span> <span class="ow"><-</span> <span class="n">keep</span>
<span class="n">choiced</span> <span class="ow"><-</span> <span class="n">lift</span> <span class="o">$</span> <span class="n">choiceResponse</span> <span class="o">$</span> <span class="n">map</span> <span class="n">snd</span> <span class="o">$</span> <span class="n">filter</span> <span class="p">(</span><span class="nf">\</span><span class="n">s</span> <span class="ow">-></span> <span class="n">fst</span> <span class="n">s</span> <span class="o">==</span> <span class="n">em</span><span class="p">)</span> <span class="n">responses</span>
<span class="n">liftIO</span> <span class="o">$</span> <span class="n">putStrLn</span> <span class="o">$</span> <span class="s">"monapo> "</span> <span class="o">++</span> <span class="n">choiced</span>
<span class="n">loop</span>
<span class="nf">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span>
<span class="nf">main</span> <span class="ow">=</span> <span class="n">runStateT</span> <span class="n">code</span> <span class="mi">0</span> <span class="o">>></span> <span class="n">return</span> <span class="nb">()</span>
</pre></div>
</div>
</div>
<div class="section" id="id14">
<h3>動かしてみよう<a class="headerlink" href="#id14" title="Permalink to this headline">¶</a></h3>
<p>せっかくつくったので少し動かしてみましょう。</p>
<div class="highlight-sh"><div class="highlight"><pre><span class="nv">$ </span>./monapoS
> こんにちわ
monapo> こんにちわ
> いいね
monapo> ピースソーグーーッド!
> だめだね
monapo> すごいHaskellたのしく学んでますか?
> だめだね
monapo> お前それサバンナでも同じ事言えんの?
</pre></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Haskellで人工無脳をつくろう</a><ul>
<li><a class="reference internal" href="#id1">はじめに</a></li>
<li><a class="reference internal" href="#id2">Haskell開発環境を用意しよう</a><ul>
<li><a class="reference internal" href="#haskell-platform">Haskell Platformのインストール</a></li>
<li><a class="reference internal" href="#cabal">cabalを使う</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id5">人工無脳の名前を考えよう</a></li>
<li><a class="reference internal" href="#id6">オウム返しさせる</a><ul>
<li><a class="reference internal" href="#id7">コードの説明</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id8">ランダムに応答を返す</a><ul>
<li><a class="reference internal" href="#haskellerhoogle">本物のHaskellerはHoogleを使う</a></li>
<li><a class="reference internal" href="#id9">コードの説明</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id10">感情モデルの作成</a><ul>
<li><a class="reference internal" href="#id11">全体の流れ</a></li>
<li><a class="reference internal" href="#id12">ロボット生命体的なアイテムの登場です</a></li>
<li><a class="reference internal" href="#id13">全コード</a></li>
<li><a class="reference internal" href="#id14">動かしてみよう</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="index.html"
title="previous chapter">ゆるふわHaskell (Light & Airy Haskell)</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="pleac.html"
title="next chapter">HaskellでPLEAC (todo)</a></p>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="pleac.html" title="HaskellでPLEAC (todo)"
>next</a> |</li>
<li class="right" >
<a href="index.html" title="ゆるふわHaskell (Light & Airy Haskell)"
>previous</a> |</li>
<li><a href="index.html">laskell 0.0.1 documentation</a> »</li>
</ul>
</div>
<div class="footer">
© Copyright 2012, kzfm.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>