29 Dec 2014, 15:57

Haskell で 関数型言語入門! edX の Introduction to Functinal Programming を受けた.

はじめに

edX で Introduction to Functinal Programming を受けた感想です. Introduction to Functional Programming | edX

今年の 2 月ごろに Ruby のブロックというものを知った. これは, いわゆる無名関数なのだが, その概念がとても新鮮だった.

それは, 関数型言語でよく利用されるということを知ったので, もっと関数型言語に触れようというのが今年の目標だった.

今年も終わりに近づく 11 月, edX で純関数型言語の Haskell の講座が開講された.

関数型言語を身につける絶好の機会だと思った.

内容

講座の内容は, 以下の本をはじめから終わりまで解説していくもの.

毎週の課題も 各章の練習問題そのものだった.

講座のスライドは github で公開されている.

感想

難しかった..でも, 学ぶことが多かった

難しかった. 1 日ずっと Haskell 漬けになったりした.

内容はさらっと解説されるのだが, 関数型言語という世界が, 今までいた世界とは異なる考え方を もっているので, 概念を理解するのに時間がかかる.

しかし, 知らない概念は刺激にもなって, おもしろい

  • モナド
  • 代数データ型
  • 遅延評価…

関数プログラミング実践入門

副読本として, 最近出版された以下の本を購入した.

この本はとても分かりやすいのておすすめ.

ボイントは, Haskell の文法に限定していないところ.

題名どおり, 関数型言語とはなにかということについてかかれている. その手段として, Haskell が解説されている.

C や Java と Haskell の比較がかかれているところがよい.

手続き型言語の世界にいるプログラマを関数型言語の世界へ 引っ張ってきたいという, 著者の意図を感じる.

数学とプログラミングの結びつきが見えた気がした

関数型言語における関数や型の概念から, プログラミングのベースには, 数学があることを強く感じた.

以下のような記事を書いている.

数学との関係性.

関数型言語のベースには数学がある.

  • 群論
  • 圏論

代数はプログラミング/ モデリングの数学的な基礎理論. 型とは代数学がベースになっている.

これからどうするか?

講座の終わりで, なんと次回予告の動画が流れた?!

Haskell の次は, 圏論 (Category Theory) の講座を予定しているらしい.

大学のとき群環体で心折れた自分としては, 代数学にやや引け目を感じるもの, 数学とプログラミングのつながりをもっ と知るためにこれも受けてみたい.

そのためには, Haskell の学習をここで終わらせることなく, 継続させたい.

AtCoder に挑戦

なにか, 計画をたてとかないと, 自分は勉強しないだろう.

継続的に学習する仕組みとして, 競技プログラミングの問題をといてみる. atcoder と, codeforces が Haskell に対応しているようだ.

Codeforces は, 海外なので深夜に開催されるが, Atcoder は日本時間に合わせて開催されているので, AtCoder をやろうと思う.AtCoder の問題を月 1 回, Haskell でとくぞ.

07 Dec 2014, 12:45

Haskell の xUnit ツール HUnit を試す

はじめに

Haskell でテストコードを書くツールをしらべてみた.

メジャーなものは以下

  • doctest
  • QuickCheck
  • HSpec
  • HUnit

各ツールの特徴

doctest

コメントにテストを書くスタイルのツール.

Python の doctest を haskell に移植したものだとか.

QuickCheck

ランダムなテストデータによって関数の性質をテストする.

xUnit とは異なるコンセプトをもつ.

HSpec

xSpec ライクなテストツール.

Ruby の RSpec にインスパイヤされたらしい.

記法が BDD 的.

HUnit

xUnit ライクなテストツール. JUnit ライク.

HUnit を試す

JUnit になじみがあるので, HUnit を試してみた.

Install

$ cabal install HUnit

Usage

Test.HUnit をインポート.

import Test.HUnit

テスト対象コード

import Data.List
import Data.Char
import Unsafe.Coerce

data Nat = Zero
         | Succ Nat
         deriving Show

natToInteger (Succ n) = natToInteger n + 1
natToInteger Zero = 0

テストコード

tests = TestList
        [ "natToInteger 1" ~: natToInteger Zero ~?= 0
        , "natToInteger 2" ~: natToInteger (Succ Zero) ~?= 1
        , "natToInteger 3" ~: natToInteger (Succ (Succ Zero)) ~?= 2
        ]

テスト実行

runTestTT (テスト関数名) でテスト実行.

$ runTestTT tests
Cases: 3  Tried: 3  Errors: 0  Failures: 0
Counts {cases = 3, tried = 3, errors = 0, failures = 0}

わざと失敗させてみる.

*Main> runTestTT tests
### Failure in: 2:natToInteger 3
expected: 1
 but got: 2
Cases: 3  Tried: 3  Errors: 0  Failures: 1
Counts {cases = 3, tried = 3, errors = 0, failures = 1}

Bookmarks

07 Dec 2014, 11:32

Java におけるポリモーフィズムの整理

はじめに

Haskell で型クラスというものを勉強した.

その延長で, 今までとてもいい加減に理解していた Java のポリモーフィズムについて再度復習した.

なんか, 用語の関係性をすごく曖昧に理解していた気がした.

Polymophism: 多相性

各要素 (定数, 変数, 式, オブジェクト, 関数, メソッドなど) についてそれらが複数の型に属することを許すという性質.

同種のクラスをカテゴリに分類してまとめ, 基本的な動作・設計部分を統一することで, オブジェクトインスタンスの扱いに柔軟性と規律を持たせるための機能.

多相性は 3 つに分類できる.

  • アドホック多相:
  • パラメータ多相:
  • サブタイプ多相:

たとえば Java だと以下に相当する.

  • アドホック多相: オーバーロード
  • パラメータ多相: ジェネリクス
  • サブタイプ多相: 継承, インタフェース

参考:

Polymorphic Type: 多相型

<div class="outline-text-3" id="text-unnumbered-3">
  <p>
    データ構造のコンテナ.
  </p>

  <p>
    データ形式に依存しないコンピュータプログラミング方式をジェネリクス プログラミングという.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AA%E3%83%83%E3%82%AF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0">ジェネリックプログラミング &#8211; Wikipedia</a>
    </li>
  </ul>
</div>

アドホック多相

オブジェクト指向におけるアドホック多相とは, オーバーロードに相当する. 多重定義ともいう.

パラメータ多相

型変数

<div class="outline-text-3" id="text-unnumbered-6">
  <p>
    多相型は宣言されたクラス, 関数に対して, 利用時に具体的な型を与える. これを型変数 (Type variable) という.
  </p>

  <p>
    Java の名前つけルールがあるらしい.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://java.keicode.com/lang/generics-naming.php">名前付けルール &#8211; Java 入門</a>
    </li>
  </ul>
</div>

Generic Type: 総称型

<div class="outline-text-3" id="text-unnumbered-7">
  <p>
    型付けされたプログラミング言語において データ型の定義とそれを参照する式 (型式) の一部にパラメタを許すことによって 類似した構造を持つ複数のデータ型を一括して定義して, それらを選択利用する仕組み.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E7%B7%8F%E7%A7%B0%E5%9E%8B">総称型 &#8211; Wikipedia</a>
    </li>
  </ul>

  <p>
    オーバーロード (overload), 継承 (inheritance) と並んでプログラミング言語において ポリモーフィズムを実現するための一つの手段.
  </p>
</div>

言語ごとの実現方法

<div class="outline-text-3" id="text-unnumbered-8">
  <ul class="org-ul">
    <li>
      Java: ジェネリクス, ワイルドカード <ul class="org-ul">
        <li>
          <a href="http://futurismo.biz/archives/2750">Java でのジェネリックスの使い方まとめ | Futurismo</a>
        </li>
      </ul>
    </li>

    <li>
      C++: テンプレート
    </li>
    <li>
      Haskell: <ul class="org-ul">
        <li>
          リスト
        </li>
        <li>
          タプル
        </li>
        <li>
          Either
        </li>
        <li>
          Maybe
        </li>
      </ul>
    </li>
  </ul>
</div>

Subtyping: 派生型

データ型 S が他のデータ型 T と is-a 関係にあるとき, S を T の派生型 (はせいがた, subtype) であるという.

基本型のデータを処理するように作られたプログラムは, その派生型のデータでも正しく処理することができる.

基本型-派生型関係ではリスコフの置換原則 (Liskov Substitution Principle) が成り立つ.

2 つの方法がある

  • インタフェース: 型をグループで分類
  • 継承: 型を階層構造で分類

inheritance: 継承

<div class="outline-text-3" id="text-unnumbered-10">
  <p>
    ほとんどのクラスベースオブジェクト指向言語では, サブクラス (インヘリタンス) が派生型の概念を実現している.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E7%B6%99%E6%89%BF_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)">継承 (プログラミング) &#8211; Wikipedia</a>
    </li>
  </ul>
</div>

override: オーバーライド

<div class="outline-text-3" id="text-unnumbered-11">
  <p>
    オブジェクト指向プログラミングにおいてオーバーライド (override) とは, スーパークラスで定義されたメソッドをサブクラスで定義しなおし, 動作を上書きすること.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89">オーバーライド &#8211; Wikipedia</a>
    </li>
  </ul>
</div>

interface: インタフェース

<div class="outline-text-3" id="text-unnumbered-12">
  <p>
    抽象データ型のメソッド.
  </p>

  <p>
    Object 型を分類し, 同じカテゴリに属するクラスに共通のインターフェイスを取り決める.
  </p>

  <p>
    implements ステートメントは, クラスたちのカテゴリ分類を明確にする方法.
  </p>

  <p>
    変数の型としてカテゴリクラスを指定すると, そのカテゴリを Implements したクラス (つまり, カテゴリに属するクラス) のインスタンスも格納できるようになる.
  </p>

  <ul class="org-ul">
    <li>
      <a href="http://homepage1.nifty.com/CavalierLab/lab/vb/clsmdl/polymorphism_02.html">ポリモーフィズムとインターフェイス</a>
    </li>
  </ul>

  <p>
    オブジェクトが, 共通のインターフェイスを実装している場合, 他のオブジェクトに置き換えることができる.
  </p>
</div>

<div id="outline-container-unnumbered-13" class="outline-4">
  <h4 id="unnumbered-13">
    どう分類するか?: 共通性/ 可変性 分析法
  </h4>

  <div class="outline-text-4" id="text-unnumbered-13">
    <p>
      オブジェクト指向のこころより引用.
    </p>

    <ul class="org-ul">
      <li>
        共通性分析:時間が経っても変化しにくい構造を見つけるもの
      </li>
    </ul>

    <p>
      共通性分析によってまとめられた概念を抽象クラスによって表現
    </p>

    <ul class="org-ul">
      <li>
        可変性分析:変化しやすい構造を洗い出すもの
      </li>
    </ul>

    <p>
      可変性分析で得た流動的要素は抽象クラスの派生クラスによって実装される
    </p>

    <p>
      設計手順:
    </p>

    <ul class="org-ul">
      <li>
        (抽象クラス) このクラスが持つ責務をすべて全うするにはどうようなインターフェイスが必要か?
      </li>
      <li>
        (派生クラス) この特定実装の中でどうのようにして与えられた仕様を実装できるのか?
      </li>
      <li>
        共通性: 時がたっても変わらないものを抽象クラスに
      </li>
      <li>
        可変性: 流動的要素を具象クラスに.
      </li>
    </ul>

    <p>
      クラスの集合がもつすべての責務を真っ当するために, インタフェースを用意する.
    </p>

    <p>
      Jim Coplien が提唱. p235 第 15 章から抜粋.
    </p>

    <ul class="org-ul">
      <li>
        <a href="http://www.amazon.co.jp/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%A8%E3%81%A8%E3%82%82%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E3%81%93%E3%81%93%E3%82%8D-Software-patterns-%E3%82%A2%E3%83%A9%E3%83%B3%E3%83%BB%E3%82%B7%E3%83%A3%E3%83%AD%E3%82%A6%E3%82%A7%E3%82%A4/dp/4894716844">Amazon.co.jp: デザインパターンとともに学ぶオブジェクト指向のこころ (Software patterns series): アラン・シャロウェイ, ジェームズ・ R ・トロット, 村上 雅章: 本</a>
      </li>
    </ul>
  </div>
</div>

型クラス

<div class="outline-text-3" id="text-unnumbered-14">
  <p>
    Haskell の概念.
  </p>

  <ol class="org-ol">
    <li>
      型は値をグループ化する.
    </li>
    <li>
      型クラスは, 型をグループ化する.
    </li>
  </ol>

  <p>
    この説明はわかりやすい.
  </p>

  <ul class="org-ul">
    <li>
      値 < 型 < 型クラス
    </li>
    <li>
      <a href="http://jutememo.blogspot.jp/2009/05/haskell.html">Haskell のモジュールの階層化と, 型クラス &#8211; パラメータ多相とアドホック多相 | すぐに忘れる脳みそのためのメモ</a>
    </li>
  </ul>

  <p>
    型を分類する点でいえば, Java のインタフェースと同義.
  </p>
</div>

おわりに

先月くらいにクラス設計をしていたときに, 会社である怖い人が,

継承とは, オブジェクトを分類するための手段なんだ!

といっていたが, ようやくその意味を理解した気がした.

29 Nov 2014, 10:47

Haskell で Hello World! しようとしたらモナドでドナドナした

file:./../img/IMG_3895.JPG

はじめに

最近発売された, Haskell 本を買ってみた.

どんな言語でも, はじめは Hello, World を出力するところからはじめる.

Haskell で Hello, World をするためには, ノマドというものを理解しない といけない. この本では p267 に書いてある. なんと険しき Hello, World…

モナドとは

とりあえず理解したことを自分の言葉でメモ. あまりわかっていない. モナドとノマドとドナドナの違いがわからない.

モナドとは, 純粋関数と副作用を共存さ競るためのしくみ.

純粋関数

同じ引数を渡す限り, どのような順番で何度呼んでも同じ結果が返るような関数.

副作用

ある機能がコンピュータの (論理的な) 状態を変化させ, それ以降で得られる結果に影響を与えること.

  • 状態を参照することで出力が変化すること
  • 状態に変化を与えることで出力が変化すること

例としては,

  • 破壊的代入
  • I/O 制御 (write/print 等)

wikipedia

ちなみに, wikipedia は,

プログラムとはクライスリ圏の射である , という要請から合成規則としてクライスリトリプル (Kleisli triple) というモナドと等価なものが用いられる.

ショボーン. 線形代数の単位を落としたオレをなめるなよ!

不条理な世の中と清められた世界

そう, Hello, World とは純粋で汚れのない pure な世界を汚す副作用.

そして, 純粋関数で構築されたプログラムは, 論理で構築された絶対的な世界!

絶対的な真理として存在する数学や音楽の秩序が美しさを持つように, 純粋関数によって構築された秩序は, それ自体が美しいのだ!

Hello, World!

コードを以下に示す.

main :: IO ()
main = putStrLn "Hello, World!"

IO という部分は, IO モナドと呼ばれる.

putStrLn は String を受け取り, IO を返す.

Prelude> :t putStrLn
putStrLn :: String -> IO ()

Bookmarks

Ruby での解説:

Haskell におけるモナドの解説ページ:

29 Oct 2014, 13:29

数学での関数とプログラミングでの関数

関数についての違和感

大学では, 応用数学を専攻していた.

大学でならった関数の定義は, ある集合から別の集合への写像だった.

就職して, C 言語でプログラムを書くようになってからずっと, どうも関数にたいして違和感を抱いてきた.

なんでこれが関数なんだ??

int main (void) {
  printf ("Hello, World!");
  return 0;
}

以下のページに同じようなことがかかれていたので引用.

x = x + 1

古き良き小学校の時代, この行には困惑させられたものだった. 魔術的な x が, 加算されたのに等しいままでいる事に. どういうわけか, プログラミングを始めると, それに構わなくなる. 「やれやれ, それは重大な事柄じゃないし, プログラミングとは現実のビジネス行為なんだから, 数学的な純粋さについてあら探しなんて必要無い (その議論なら, 大学にいる狂った髭面野郎どもにさせておけばいい) 」と思っていた. けれども, ただ知らなかっただけで, 我々が間違っていて高い代償を支払っていたのは 明らかである.

Haskell における関数の定義

最近, プログラミング Haskell という本を読んだ.

その中での関数の定義を読み, 自分が思ってきた関数のイメージと一致した.

関数は, ある型の引数を他の型の引数の結果に変換する. 型とは, 互いに関連する値の集合.

これだ! と思った.

これが大学でならった関数の定義だ. 関数型言語というのは数学に近いときいていたが, それを感じた瞬間だった.

うれしかったので, 今回の記事にしてみた. もっと, 関数型言語について知りたいと思った.

C 言語と Java における関数の定義

C 言語 (手続き型) と Java (オブジェクト指向型) における関数の定義について も, Wikipedia で調べてみたので, 書いておく.

関数型における関数とは, 意味するところは違う. これが, 違和感の正体だった.

C 言語 (手続き型パラダイム)

戻り値つきのサブルーチン.

プログラム中で意味や内容がまとまっている作業をひとつの手続きとしたもの.

Java (オブジェクト指向パラダイム)

あるクラスないしオブジェクトに所属するサブルーチン.

各オブジェクトが持っている自身に対する操作. オブジェクトは「データ」と「手続き」から成っているが, その「手続き」の部分に当たる.

22 Oct 2014, 14:52

Haskell を快適に利用するための Emacs 環境の構築

edX で Haskell の講座をとり始めました.

内容はさておき, まずは Emacs の環境作りから始めました.

環境づくりに夢中になって内容がおろそかになるという, いつもの悪いパターン.

haskell-mode

Haskell のマイナーモード.

(autoload 'haskell-mode "haskell-mode" nil t)
(autoload 'haskell-cabal "haskell-cabal" nil t)

(add-to-list 'auto-mode-alist '("\\.hs$" . haskell-mode))
(add-to-list 'auto-mode-alist '("\\.lhs$" . literate-haskell-mode))
(add-to-list 'auto-mode-alist '("\\.cabal\\'" . haskell-cabal-mode))

モードの設定.以下のリンクが詳しい.

 ;; indent の有効.
(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
(add-hook 'haskell-mode-hook 'font-lock-mode)
(add-hook 'haskell-mode-hook 'imenu-add-menubar-index)

Haskell Script の編集モード

(add-to-list 'interpreter-mode-alist '("runghc" . haskell-mode))
(add-to-list 'interpreter-mode-alist '("runhaskell" . haskell-mode))

Haskell でかかれたスクリプトを haskell-mode で編集する.

#!/usr/bin/env runhaskell

Ghci との連携

M-x run-haskell で ghci が起動.

(setq haskell-program-name "/usr/bin/ghci")

C-c, C-l でも起動.

(add-hook 'haskell-mode-hook 'inf-haskell-mode) ;; enable

ghci の起動とファイルの読み込みを一緒に行う設定.

(defadvice inferior-haskell-load-file (after change-focus-after-load)
  "Change focus to GHCi window after C-c C-l command"
  (other-window 1))
(ad-activate 'inferior-haskell-load-file)

- inferior-haskell-mode で設定すると便利なこと - プログラムとかのの blog

gcd-mod

Haskell 開発を助ける機能がそろったツール.

Install

% cabal update
% cabal install ghc-mod

Settings

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

Emacs での使い方は以下のページに書いてある.

エラーチェック

flymake

構文チェック.

(add-hook 'haskell-mode-hook (lambda () (flymake-mode)))

hlint

コードチェック. cabal install hlint でインストールする. C-c C-c でカーソル部のチェック.

自動補完

こんなの見つけた. ac-haskell-process.

(require 'ac-haskell-process) ; if not installed via package.el
(add-hook 'interactive-haskell-mode-hook 'ac-haskell-process-setup)
(add-hook 'haskell-interactive-mode-hook 'ac-haskell-process-setup)
(eval-after-load "auto-complete"
  '(add-to-list 'ac-modes 'haskell-interactive-mode))

Links