bigpadノート

プログラミング寄りの内容を書いてます。

1章 WebSocketを使ったチャットアプリケーション(シンプルなウェブサーバー)

(Mac OS X El Capitanを基本に書いています)

最初のプログラムとしてブラウザを使ったチャットアプリケーションを作ってみよう。 ブラウザとサーバーはWebSocketを使って通信することにします。 WebSocketっていうのはウェブサーバー/ブラウザ間の双方向通信を行う技術です。 通信がつながると、ブラウザ起点の通信だけでなく、サーバー起点の通信も可能になります。 詳しくはWikipediaを見てね。

これは書籍「Go言語によるWebアプリケーション開発」を使って Haskellの勉強をしようというシリーズです。 Haskellは書籍「関数プログラミング実践入門 ──簡潔で、正しいコードを書くために (WEB+DB PRESS plus)」を読んで勉強中。

表記について

以降の説明では次の表記を使います。

コマンド

$ echo これはコマンド実行です
これはコマンド実行です

$始まりの行が入力したコマンド行で、それ以外は出力された行か補足です。 出力が多い時は:で省略します。 なおrootユーザーでのコマンドは#始まりで表記します。

ソースコード

-- 入門プログラム
main = putStrLn "Hello, World!"

使用パッケージの選定

Haskellには多くのウェブフレームワークが用意されています。

今回はウェブフレームワークのひとつYesodで使われているWAIWARPWAI WebSocketsと、WebSocketsHTTP types、あとGingerを使うことにしました。

WAI

WAIHaskellのウェブサーバー/フレームワークの共通インタフェースを提供します。 CGIWSGIみたいなものでしょうか。

Warp

WarpはWAIを使ったHaskellのHTTPサーバーライブラリです。 RubyWEBrickみたいなものでしょうか。

WAI WebSockets

WAI WebSocketsはWAI上でWebSocketsを使うためのライブラリです。

WebSockets

WebSocketsHaskellでWebSocketサーバーを実装するためのライブラリです。

Ginger

GingerHaskellのテンプレートエンジンです。 PythonのJinja2をHaskellで実装したもののようです。

シンプルなウェブサーバー

まずはパッケージの準備を行ってシンプルなウェブサーバーを作ってみましょう。

プロジェクト用ディレクトリ作成

プロジェクトを作りたいディレクトリに移動し、stack newでプロジェクトディレクトリを作ります。 今回は~/proj/にchatプロジェクトを作ってそこで作業をします。

$ cd ~/proj
$ stack new chat
Downloading template "new-template" to create project "chat" in chat/ ...
The following parameters were needed by the template but not provided: author-email, author-name, authorName, category, copyright, github-username
You can provide them in /Users/big/.stack/config.yaml, like this:
templates:
  params:
    author-email: value
    author-name: value
 :
Or you can pass each one as parameters like this:
stack new chat new-template -p "author-email:value" -p "author-name:value" -p "authorName:value" -p "category:value" -p "copyright:value" -p "github-username:value"

Using cabal packages:
- chat/chat.cabal
 :
Writing configuration to file: chat/stack.yaml
All done.
$cd chat

この出力ではパラメータ指定がされていないと出ています。 今回はサンプルですので省略しましたが、実際のプロジェクト時には作者やメールアドレスなどを指定します。(いつか調べたい)

Cabalファイル編集

まず作られたchatディレクトリにあるchat.cabalファイルを編集します。 Libraryセクションのbuild-depends:に使用するパッケージを追加します。

 :
library
  hs-source-dirs:      src
  exposed-modules:     Lib
  build-depends:       base >= 4.7 && < 5
                      -- ここに使用パッケージ追記
                      , http-types
                      , wai
                      , warp
  default-language:    Haskell2010
 :

ソースファイル編集

次にchat/src/Lib.hsファイルを編集しましょう。 とりあえずsomeFunc関数を書き換えていきます。 今回は短いので全て引用しておきます。 参考ページ

{-# LANGUAGE OverloadedStrings #-}

module Lib
    ( someFunc
    ) where

import           Network.HTTP.Types        (status200)
import           Network.HTTP.Types.Header (hContentType)
import           Network.Wai               (Application, responseLBS)
import           Network.Wai.Handler.Warp  (run)

someFunc :: IO()
someFunc = do
  let port = 3000
  putStrLn $ "Listening on port " ++ show port
  run port app

app :: Application
app req f =
  f $ responseLBS status200 [(hContentType, "text/plain")] "Hello world!"

1行目 {-# LANGUAGE OverloadedStrings #-}

文字列リテラルである"〇〇"の扱いを変更します。 今回使用するパッケージが[Char]ではなく、ByteStringを要求するためです。

3〜5行目 module

外部に提供するものを書きます。 雛形ではLibモジュールとしてsomeFuncを提供しています。

7〜10行目 import

使用するパッケージを書きます。 今回は何がどのパッケージかわかるように使う要素も(〇〇)で指定しています。

13〜16行目 run port app

Warpを利用してポート番号とApplicationを渡してサーバーを起動しています。

18〜20行目 app :: Application

WAIのApplication型を定義しています。 リクエストに対してレスポンスとしてstatus:200context-type:text/plainと内容Hello world!を返すように定義しています。

アプリビルド

chatディレクトリでstack buildしてみましょう。 初回はCabalファイルに追加したパッケージのインストールが行われるため、かなり時間がかかります。

$ stack build
 :
chat-0.1.0.0: build
Preprocessing library chat-0.1.0.0...
 :

アプリ実行

ビルドが成功したら、実行してみましょう。

$ stack exec chat-exe
Listening on port 3000

ブラウザでhttp://localhost:3000にアクセスすると、Hello world!メッセージが表示されれば成功です。 パチパチパチ〜

使われている基礎構文の説明

Haskell 2010 言語報告書
ちゃんと言語報告書を読んだわけではなく、実際のコードから推測したりググって調べたものを書いています。まだHaskellに慣れていないので勘違いがあったらごめんなさい。

コメント

--から改行まではコメントとして扱われます。 ただし、他の構文に使われる字句の一部の場合はそっちが優先されます。 例えば-->|--はコメントとしては扱われないです。 なので慣習的に前後に空白を置いて書かれることが多いようです。

コメントが複数行になる場合は{--}で囲むと改行を含めてコメントとして扱われます。 この形式のコメントは入れ子にできるので、ネストコメントと呼びます。

以下がコメント例です。

-- これは1行コメント
{- これは複数行コメント
   改行もOK
   {- ネストできます
   -}
   ここもコメントです
-}
-- {- ここは1行コメントです
this_is_NOT_comment = "コメントアウトの切り替え"
-- -}

最後のコメントがネストコメントのようにも見えますが、コメントアウトのイディオムです。 ネストコメントの終了を-- -}としておくと、開始部分を1行コメントにするかどうかで、コメントアウトの切り替えができます。

また、ネストコメントはコンパイラへのプラグマ指定としても使われます。 今回のコードでは{-# LANGUAGE OverloadedStrings #-}が使われています。

次回予定の記事で扱いますが、ソースコードとその中のコメントからドキュメントを自動生成するhaddockというツールもあります。 -- |{- |-- ^{- ^始まりのコメントがドキュメント化されます。

識別子

  • 変数識別子小文字アルファベット始まりで、英字・数字・シングルクォートが0個以上続くもの
  • 構成子識別子大文字アルファベット始まりで、英字・数字・シングルクォートが0個以上続くもの

識別子は小文字、大文字を区別し、アンダースコア_は小文字とみなされます。 また、_始まりの識別子はコンパイラの未使用警告を抑制するようです。

型推論

Haskellには型推論機能があります。 わざわざ書かなくても自明なものはコンパイラが自動で推測してくれます。 ただ、自明じゃないものや人に向けたドキュメントとして型を指定することもできます。

::で型を指定します。 someFunc :: IO()app :: Applicationが型指定です。 左側の小文字始まりのものが変数名(関数名)で、右側の大文字始まりのものが型になります。 IO()()が何を指しているかは勉強不足です。。。

let式 / where節

letで式中でのみ有効な一時的な定義を行うことができます。 似たような構文としてwhere節があります。 whereは式中ではなく、宣言全体で有効な一時的な定義を行うことができるようです。 きっとmodulewhereもそういうものなんでしょう。

演算子

Haskellでは演算子を自分で定義することができます。 用意されている演算子+,-,*,/などよくあるものや、$++など見かけないものがあります。 (私は普段C++を使っています)

  • $は関数適用を行います。通常は左結合の所を右結合にできます。関数の引数として別の関数の結果を使いたい場合に()を省略できて便利です。

  • ++はリストの結合です。文字列リテラルは文字のリストなので、++を使って結合します。

付録A 安定した開発環境のためのベストプラクティス(を知りたい)

オリジナルと合わせてベストプラクティスと題したけど、 ベストではなく1つの方法としてお読みください。 (Mac OS X El Capitanを基本に書いています)

これは書籍「Go言語によるWebアプリケーション開発」を使って Haskellの勉強をしようというシリーズです。 Haskellは書籍「関数プログラミング実践入門 ──簡潔で、正しいコードを書くために (WEB+DB PRESS plus)」を読んで勉強中。

表記について

以降の説明では次の表記を使います。

コマンド

$ echo これはコマンド実行です
これはコマンド実行です

$始まりの行が入力したコマンド行で、それ以外は出力された行か補足です。 出力が多い時は:で省略します。 なおrootユーザーでのコマンドは#始まりで表記します。

ソースコード

-- 入門プログラム
main = putStrLn "Hello, World!"

Haskellのインストール

手軽に試すならHaskell Platformという、 コンパイラ、ビルドシステム、開発ツール、よく使われるパッケージをひとつにまとめたものがあります。

これでもよかったのですが、stackという開発環境管理ツールナウいらしいです。 新しいもの好きな私はstackでインストールすることにしました。

stackはコンパイラのインストールやパッケージインストールを手助けしてくれます。 またビルドシステムとしても使えパッケージの依存関係を管理してくれるため、 時々ある依存バージョン地獄に悩まされなくなって安心できます。 おかげでshebang指定でのスクリプトとしても安心して使えるようです。(Stackを使って楽しくHaskellスクリプティング)

参考ページ

Mac OS Xへのインストール

私はAnsibleを使います。 (今回はbrew install haskell-stackだけですが)

Githubにアップしているstack_osx.ymlをダウンロードしてインストールできます。 Ansibleが入っていれば、次のコマンドでOK!

$ ansible-playbook stack_osx.yml
[WARNING]: provided hosts list is empty, only localhost is available
PLAY ***************************************************************************
TASK [homebrew] ****************************************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0

$ stack --version
Version 1.0.4 x86_64

補足 Ansibleのインストール

  1. Xcodeインストール

    $ sudo xcodebuild -license
     or
    $ xcode-select --install

  2. Homebrewインストール

    $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

  3. Ansibleインストール

    $ brew install ansible
    $ ansible --version
    ansible 2.0.1.0
    config file =
    configured module search path = Default w/o overrides

Windows 10へのインストール

私はWindows 64-bit Installerを使いました。

ダウンロードしたインストーラーを実行!

Haskellの設定

stackを使ってHaskellコンパイラをインストールします。 必要があればHTTP_PROXY環境変数を設定しておいてください。

まずはstackが使えるか確認してみましょう。

$ stack --version
Version 1.0.4 x86_64

ではコンパイラGHCをインストールしましょう。

$ stack setup
Run from outside a project, using implicit global project config
Using latest snapshot resolver: lts-5.8
Writing implicit global project config file to: /Users/big/.stack/global-project/stack.yaml
 :
Installed GHC.
 :

これでGHCが使えるようになりました。

$ stack ghc -- --version
Run from outside a project, using implicit global project config
Using resolver: lts-5.8 from implicit global project's config file: /Users/big/.stack/global-project/stack.yaml
The Glorious Glasgow Haskell Compilation System, version 7.10.3

プロジェクト単位の設定

stackを使うとシステムの環境とプロジェクトの環境を分けられます。 プロジェクトごとに環境を用意することで、それぞれで同じパッケージを使用していても 別のバージョンをインストールことができます。

まずはプロジェクトを作成して、作られたディレクトリに移動しましょう。

$ stack new helloworld
Downloading template "new-template" to create project "helloworld" in helloworld/ ...
 :
$ cd helloworld
$ ls
LICENSE helloworld.cabal test Setup.hs src app stack.yaml

次にプロジェクト用にセットアップを行います。 通常はグローバルプロジェクトにインストールされますが、 依存するライブラリのバージョンによってはプロジェクトローカルにインストールされます。

$ stack setup
stack will use a locally installed GHC
For more information on paths, see 'stack path' and 'stack exec env'
To use this GHC and packages outside of a project, consider using:
stack ghc, stack ghci, stack runghc, or stack exec

そしてビルド。

$ stack build
[1 of 1] Compiling Main
 :
Registering helloworld-0.1.0.0...

すると実行ファイルが作られるので、次のコマンドで実行!

$ stack exec helloworld-exe
someFunc

stack teststack benchstack haddockなど他にも便利機能が用意されています。

Haskellツール

Haskellの開発をサポートするツールがたくさん用意されています。 その中のいくつかを紹介しましょう。

stack install パッケージインストール

stack installgo getpipのようなパッケージインストールができます。

使い方

$ stack install ghc-mod stylish-haskell
 :
Copied executables to /Users/big/.local/bin:
- ghc-mod
- ghc-modi
- stylish-haskell
WARNING: Installation path /Users/big/.local/bin not found on the PATH environment variable

パッケージが多いと、とっても時間がかかるので注意。

最後に書いてあるように、~/.local/binをPATH環境変数に登録することでインストールしたツールをstack経由でなく直接実行できるようになります。 ついでにstack ghcstack ghciをaliasでghcghciとしとくと便利です。

stylish-haskell ソースコード整形ツール

stylish-haskellgo fmtclang-formatのようなソースコードを整形してくれます。

stackからインストールできます。

$ stack install stylish-haskell

使い方

$ stack exec stylish-haskell -- -i app/Main.hs

HLint ソースコード検査ツール

HLintgo vetlintのようなソースコードを検査してくれます。

stackからインストールできます。

$ stack install hlint

使い方

$ stack exec hlint app/Main.hs
No hints

Emacs

各種エディタには開発を補助する拡張機能が用意されています。 ここではEamcsの拡張機能を少しご紹介しましょう。

ghc-modは1つのプログラムで、エディタと通信して使用します。 使うためにはghc-modをインストールしておく必要があります。 これもstackからインストールできます。

$ stack install ghc-mod  :
Copied executables to /Users/big/.local/bin:
- ghc-mod
- ghc-modi
WARNING: Installation path /Users/big/.local/bin not found on the PATH environment variable

ghc-modを直接使えるように、まだPATH環境変数に登録していなければ最後に出力されたパスを~/.bash_profileに登録します。

ではEmacsの設定をしていきます。まずMELPAを使えるように~/.emacs.d/init.elに次のコードを書いておきましょう。

(require 'package)
(add-to-list 'package-archives
         '("melpa" . "https://stable.melpa.org/packages/"))
(package-initialize)

Emacsを起動して、M-x package-list-packageでパッケージ一覧を表示します。 下記をそれぞれ探してi(インストールマーク)。マークをつけたらxでインストール。 - ghc - haskell-mode

~/.emacs.d/init.elに下記のHaskell用の設定を追加したら準備完了!

(autoload 'ghc-init "ghc" nil t)
(autoload 'ghc-debug "ghc" nil t)
(add-hook 'haskell-mode-hook (lambda () (ghc-init)))

お好みでHaskell > Customizeを設定したり、init.elに追記して使いやすくしましょう。 私はhaskell-stylish-on-saveを有効にしてソースコード保存時に整形しています。

2016年1月 読書感想文 Go言語によるWebアプリケーション開発

「新春座談会 このコンピュータ書がすごい! 2016年版 —2015年に出たコンピュータ書ならこれを読め!—
↑これを今年初めてライブストリーミング配信で見て、いっぱい本が出てるなーと、いっぱい紹介できてすげーなーと。
そこで今年は毎月1冊新作技術書を読んで勉強しようと思いました。1冊のピックアップは毎月15日頃Amazon PCサイトの詳細検索を使って発売月を指定して検索して、その中で1番興味を持ったものを買います。

1月は「Go言語によるWebアプリケーション開発」洋書タイトル「Go Programming Blueprints」

Go言語によるWebアプリケーション開発

Go言語によるWebアプリケーション開発

この本はだいぶ面白かった。買ってよかった。


私のGolangレベルは新しい言語をGoogleが出したんだなー、型指定がC言語と違って後ろなんだなー、並行処理が楽に書けるんだなー、程度の知識です。
C++はプログラム作る程度には使えるので説明とコードを見れば何をしているのかなんとなくわかりました。
Go言語はシンプルな構文で読みやすいですね。


この本には簡単なものですが、チャットアプリ、Web APIの使用と作成、コマンドラインツール、NoSQL、といった実際のプロダクトを作って学ぶ形式でした。
言語の勉強だと意味のないサンプルコードが多いですが、実際にアプリを作りながら学べるから面白い。

また、アプリを作るだけじゃなくて、TDDで作っていくというプログラミングの作成環境としてのGoについても書いてありいいなと思いました。普段はVisual Studioで開発してて、TDDはやりたいなーと思ってるけどなかなかできないのでいい刺激にもなりました。


同じ頃 Haskell を勉強し始めたから、この本に沿って Haskell の勉強にも使ってみようかと計画中。GoとHaskellどっちが今後自分の道具となるだろうか。
今選べるプログラミング言語
・単純なツールなら:Windowsバッチ、Ant
・ちょっと複雑なら:Ant、C#
・製品レベルなら:C++C#
ここにGoやHaskellが入ればもっと楽にプログラムが作れるんじゃないかなーと。

MacBook Air 13インチを買った

新しいMacBook Airが出てすぐに買った。
iPadの母艦であり開発機にしようと思う。

Macでまだまだ慣れないけどちょっとずつ使って覚えていこう。
もう少しでMountain Lionが出るのでそれまでは試運転。

とりあえず今インストールしたもの。

KeyRemap4MacBook

http://pqrs.org/macosx/keyremap4macbook/
これを使ってJIS配列のキーボードをUS配列にした。
それだけじゃなく、英数とかなキーを別のキーにしたりといろいろ書き換えた。
まだ空きキーがあるので今後必要になったら追加していこうと思う。

SourceTree

http://itunes.apple.com/jp/app/sourcetree-git-hg/id411678673?mt=12
個人でMercurialを使っててGUIで操作できるクライアントを調べたらこれが見つかった。
いつかGitも使うかも知らんので両方対応してるのはよさそう。
まずはKeyRemap4MacBookの設定ファイルを管理してみた。

iPadに入れたアプリ

iPadを手に入れて2週間。週末にしか長時間使ってないけど、現在インストールしたアプリを記録しとこう。

電子書籍関連

とりあえずストアアプリをたくさんインストールしておいた。
今度陳列をみてリストラしていくつもり。

iBooks

http://itunes.apple.com/jp/app/ibooks/id364709193
現在はこれで自炊PDFを読んでる。もっとメモがとりやすいものにしたいが、有料アプリになってくるので熟考中。

雑誌ONLINE

http://itunes.apple.com/jp/app/za-zhionrain+books/id324946616
名前からすると雑誌がメイン?

常用アプリ

よく使うであろうアプリたち。

SHOT NOTE

http://itunes.apple.com/jp/app/shot-note/id411332997
iPhoneアプリしかなかったが、ノート買ってしまったので入れてる。勉強したノートをショットしていきたい。

3D視力回復

http://itunes.apple.com/jp/app/3d-shi-li-hui-fu/id453629018
ずっとモニタを見つめて、ピント調節が固まってしまったときに使用してみようと思って購入。が、見た目がしょぼかった。
これは有料アプリ。目的はそこそこ達成できるし、85円だけどなんか失敗感を味わった。
このおかげで有料アプリはしっかり調査してから買おうと決めました。

GoodNotes

http://itunes.apple.com/jp/app/goodnotes-wu-liao-ban-shou/id483679173
ノートアプリ。手書きも拡大画面で入力できて細かい字も書けるのでいいね。
無料版をインストールしたけど、有料版にバージョンアップしてもいいかもしれない。
無料版の2ファイル限定が解除されたらメモができるPDFリーダーとしても活用するかも。
PDF上に手書きできるし、マーカーもあるし、ノートページを挿入することも出来る。
PDFリーダー候補。

UYH

http://itunes.apple.com/jp/app/shou-shukitsuru/id317514393
あとでやろうと思いついたことをリスト形式で保存してる。
チェックリストとして使えて、なにより文字が綺麗に見える。
手書き文字がきたない俺でもなんかイイ!ってなった。スタイリッシュって大事だな。

AppBank

http://itunes.apple.com/jp/app/appbank-for-ipad/id364223227
いろんなアプリのレポートがあってアプリ選びの参考にさせてもらってます。

クラウド

クラウドを専用アプリとして使えるようにしたものたち。

SugarSync

http://itunes.apple.com/jp/app/sugarsync/id288491637
Evernote,DropBox,SugarSyncの3つどれを使おうか検討したとき、無料の容量が一番大きかったSugarSyncになった。
同期機能は使ってなくて、ただのネットワーク上のドライブとして使用中。
ネットワーク上のドライブとしてなら後述のNドライブのほうが容量多くていいと思い出した。
他アプリ連携を考えたらEvernoteDropBoxの方が便利だとも思い出した。
SugarSyncとのお別れも近いかも。

Nドライブ

http://itunes.apple.com/jp/app/naver-ndoraibu-for-ipad/id413617492
ネットワーク上のドライブとして使用するなら30GBの容量が無料で使えるNドライブがいい。
と最近知った。ただアプリでダウンロードしたものはOpenInが使えず、Nドライブ内でしか開くことが出来ない。残念。
ブラウザからダウンロードすればOpenIn使えるだろうか?と思ってるけどまだ試せていない。

RTM

http://itunes.apple.com/jp/app/remember-the-milk/id293561396
Remember The Milkというタスク管理アプリ。
前から気になっててようやく登録してみる気になった。
まだ登録してないけど。常時接続じゃないから、オフラインでどれくらい使えるかが気になるところ。

なんとなく入れてみた

暇なときに見たり、いつか必要になるかと思って入れてるものたち。

e国宝

http://itunes.apple.com/jp/app/e-guo-bao/id413457009
国立博物館所蔵の物が画像と解説をみれてなんかいい。
オフラインで使えなかったのが残念。

路線図

http://itunes.apple.com/jp/app/marugoto-lu-xian-tu/id417547679
ちょっと旅に出たくなったときに眺めて行き先をきめるとか出来そう。

OneNote

http://itunes.apple.com/jp/app/microsoft-onenote-for-ipad/id478105721
画像つきの文章が書ける。
日常の何気ない日記につかえるかもとか思った。まぁ日記書いてないけど。

SketchBookX

http://itunes.apple.com/jp/app/sketchbook-mobilex/id327376639
すごいお絵かきアプリ。すごすぎて何が出来るかわからず放置。
いつか使うときが来るかもしれない。

iPadファーストインプレッション

一日iPad触ってみた。まだ全く使いこなせていないが、使いこなせたら便利そうだと思った。
とりあえずキーボードが打ち辛いけど、音声入力が意外と精度が高くて便利に使える。まあ家で居る時位しか使えないけど。
この日記も音声入力を中心で書いてみた。普段喋らないから滑舌を良くする練習にもなっていいねw

まずは電子書籍を閲覧するアプリを決めたい。
pdfにメモを書き込めるのが良いな。手書きができると便利。
小さいサイズの本だったら横に並べて見開きで見たい。ただ小さい本だったらSonyのReaderのほうが見やすいかも。

あとブラウザーで戻るをジェスチャーでできるやつはあるんかな?ページを戻る操作がめんどくさい。

明日は指紋防止用の保護フィルムを探してこよう。いちにち触ってたら指紋だらけになった…

新しい〜iPadを手に入れた

ついにiPadオーナーになった!
まず初めにApple IDの登録がサーバーのブロックでうまくできなかった。
時間をあけて何回か試したけど結局だめだったので、その部分の設定を諦めてスキップした。サーバーが混雑してんのかなぁ〜。

正直何から始めていいかわからん。
とりあえず設定をいろいろ見てみて必要そうなものを変更した。
そこでSafariをプライベートブラウズにしてCookieも拒否してみたら、はてなダイアリーにログインできなかった。
だめなサイトはどういうのがあるかしばらく使って試してみようと思ってたのに出鼻でくじかれたorz
普通にブラウズしようか。

次はiPadガイド読んでみようかと思う。