19 Jun 2015, 12:29

Wrap-Unwrap Pattern についての覚書

Functional Python Programming という本を読んでいたら、 Wrap-Unwrap Pattern というものを知ったので、ちょっとメモ.

公式

unwrap(process(wrap(iterable)))
  • wrap() ラッパー
  • unwrap() アンラッパー ラッパーで処理したものをもとに戻す.
  • process() 処理したい手続き
  • iterable 処理したいデータ

ラッパーは、iterable なデータをタプルに加工する. タプルを利用するのは、タプルが immutable なデータ構造だから.

例: 最大値を求める

以下、python による例です.

以下のデータ構造で身長が最大の人を調べる.

  • 太郎: 170
  • 次郎: 160
  • 三郎: 180
students = [("Taro", 170), ("Jiro", 160), ("Saburo", 180)]

max 関数は、そのままでは利用できない.

>>> max(students)
('Taro', 170)

ラッパーでタプルを作成する. wrap 関数は、generator expression ともいう.

def wrap(students):
    return ((student[1], student) for student in students)

def unwrap(data):
    length, student = data
    return student

パターンを適用.

unwrap(max(wrap(students)))

>>> unwrap(max(wrap(students)))
('Saburo', 180)

その他

wrap 関数をいちいち定義するのは面倒なので、lambda が利用される.

>>> max(map(lambda s: (s[1], s), students))[1]
('Saburo', 180)

map を利用する場合の方が、generator expression よりも、高速らしい.

unwrap の操作でタプルの一番目、二番目を取り出すのは常套手段. なので、Haskell には、fst,snd という関数が用意されている.

  • fst: タプルの 1 番目の要素を取り出し
  • snd: タプルの 2 番目の要素を取り出し

26 May 2015, 10:18

Java8 Stream をつかって宣言的な計算で遊んでみた

関数型の書き方に早く慣れ親しみたいので、 Java による関数型プログラミング を買ってみました.

今日は、 簡単な演算を stream で実施するとどうやるかをいろいろ実験してみました.

forEach

forEach は 各ストリーム要素に大してなんらかの操作をすることができる.

表示

print 表示してみる.

import java.util.*;

class StreamSample {
    public static void main(String args[]) {
        List<Integer> list = Arrays.<Integer>asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        list.stream().forEach(i -> System.out.print(i + " "));
    }       
}
// 1 2 3 4 5 6 7 8 9 10 

reduce

集合から単一の値を求める.

すべての合計を求める

sum()と average()などによる集計の機能は Stream には用意されていない. mapToInt()をつかうことで、Integer 型を int 型に変換する.

int sum = list.stream()
         .mapToInt(x -> x)
     .sum();
System.out.println(sum);

最大値を求める

int max = list.stream()
    .mapToInt(x -> x)
    .max()
    .orElse(0);
System.out.println(max);

すべての積を求める

とくに、専用メソッドはないようだ. reduce メソッドで実装する.

int multiple = list.stream()
    .mapToInt(x -> x)           
    .reduce(1, (a, b) -> a * b);
System.out.println(multiple);       

filter

filter を用いることで、if 文相当のことができる.

// 奇数のみの足し算
int sum2 = list.stream()
    .mapToInt(x -> x)
    .filter(i -> i % 2 == 1)        
    .sum();
System.out.println(sum2);

おわりに

以上、簡単に書籍を参考にしながらコードを動かしてみた.

java で関数型プログラミングを学ぶと、 慣れ親しんだ言語ということでとっつきやすい.

しかし、関数型ならば Java じゃなくて Scala とか、 本格的な言語で学んだほうがよいのではないかというジレンマもある.

当初の目論見では、TopCoder の問題を関数型で書き直して学ぼうとおもったけれども、 TopCoder の問題は思った以上に配列を多用しているため、ちときつい.

おそらく、Java で 関数型を学ぶとすると、 仕事で Java8 以降の開発に携わることができたときかな。 今の職場じゃ絶望的…早くコイコイ関数型の時代.

Special Thanks

以上、Happy Hacking!!

11 Feb 2015, 02:20

関数型言語 (Scala) をどうオブジェクト指向の現場に持ち込むか? セミナーをきいた感想

はじめに

今日は, なんだか仕事のやる気も起きないアンニュイな気分だったので, 仕事をサボって社内で開かれたセミナーを聴きにいきました.

Scala による OO と FP のお話

スピーカーは, 浅海智晴さん.

話の内容は, “オブジェクト指向と関数型プログラミング (Scala)“について.

用語を復習しようと Google で検索していたら, 今日きいた話のスライド発見. 一生懸命メモをとったものの, ラッキー.

以下, 用語についての復習と感想を書く.

背景

ハードウェアのメニーコア, 大容量メモリ化によって, 性能のボトルネックが I/O ではなくて, アプリケーションとなってきた. アルゴリズムが勝負の世界. アプリがボトルネックになってきた. そのため, 言語レベルで平行・並列処理が書きやすい言語が求められるようになった.

Cloud Computing において, 異常が発生したら全体をとめるのではなくて, 一部を停止して運用を継続させる必要がある.従来の例外処理では処理する のが複雑になってきた.そのため, 言語レベルで分散コンピューティングや Fault Tolerant をサポートするような言語が求められるようになった.

所感

ストレージ業界にいることもあって, アプリが性能のボトルネックになるというはなしはよくきく.

以前, 次世代メモリと呼ばれている ストレージ・クラス・メモリ (SCM) の技術動向の話をきいたときにも同じはなしが出た. アプリがストレージの性能のボトルネックになるとわかったとき, 我々開発者はなにをすればいいのか? という質問がでたが, 答えは,

関数型言語をつかうこと

All SCM Array が数年後に実現したときにはじめて, プログラミングの パラダイムシフト が起こるかもしれない.

関数型言語とは

過去と現在の関数型言語の認識の違い.

昔は, 高階関数 をサポートする言語という緩い定義だった.

現代のモダンな言語の定義は違う!

現代のモダンな言語 (Haskell, Scala など) は,

数学的理論を背景にプログラムを記述する言語

数学をベースとするプログラミング

数学的理論とは, たとえば以下.

  • ラムダ計算
  • 数理論理学
  • 圏論

とりわけ, Monad が大事.Monad をつかって, どうつくるかという流れ.

所感

数学のベースについて, 以下の記事でまとめられているが,これがおもしろい. 数学がベースといってはいるものの, 数学のほんの一部分.抽象代数学がからんでいる.

自分は, 大学では一応応用数学を学んだ気がしたので, プログラミングと数学が結びつくという売り文句はとてもうれしいのだ.

ああ, 学生時代の苦しみは無益ではなかったのだと.

代数学は, 禅僧の修行のような単なる苦悩に耐え忍ぶ訓練だと思っていたので, まさか, 社会人になって再び群論にお目にかかるとは,学生のときには想像 出来ないことだった.

コンパイル = 証明

コンパイルを通すということは, 正しさを証明すること

関数型言語では, コンパイルが通るとバグがほとんどでない. 純粋関数の世界でプログラミングをすることによって, 実現できる. 背景には数理論理学がある.

このことがなぜ大事かというと, 並列プログラミングのバグとりは大変. テストですべてのバグをとれたという保証ができない.

関数型ならば数学をベースにして, バグがないことを証明することができる

関数型言語のメリット・デメリット

  • メリット
    • 高階関数を使った技が使える (それによってコードが短くなる)
    • 定理と証明
  • デメリット デメリットだけみると, 組み込み系ではほとんど出番なしな気がした. いつの時代も, C 言語最強?? いや, C で並列処理はつらい.

    質問時間に, 組み込み系では関数型言語は活用できますかと 質問してみたが, わかりませんという回答だったので, 調べてみた.

    有力候補は OCaml. 時間効率, 空間効率がいいらしい.

    マイナーな言語で ATS というものもあるが, 情報が少ない.

    分散システムを組むならば, Erlang もつかえるか? - 組み込みから生まれた言語 Erlang の時代が来る - 日経エレクトロニクス

    組み込み系といっても, リッチな環境の組み込み系ならばリソースなんて 関係ない?? Android は Java で動いているし, Scala だって.

Monadic Programming

モナドを中心にプログラムを組む方法.

モナドとは,

  • コンテナ
  • パイプライン
  • インタプリタ

モナドにはいろいろな種類がある.

  • IO モナド
  • State モナド
  • Future モナド …

モナドの使い方は難しいのだけれども, パターンがあるのでなれれば簡単.

所感

モナドはよくわからない.

しかし, 今日の話で距離が狭まった.

難解なもの, 副作用をもつものは, モナドに閉じ込めて隠蔽する. それによって, プログラムがスッキリする.

この言い回しは, OO におけるカプセル化 でもきいたような気がする.

難解なもの, 副作用をもつものは, オブジェクトに閉じ込めてカプセル化する. それによって, プログラムがスッキリする.

また, モナドには使い方があり, 覚えてしまえば簡単という話は, 以前まとめた関数型デザインパターンの話にもつながるのかもしれない.

Functinal Reactive Programming (FRP)

ある変化に応じて動作する, イベント駆動のプログラミング方法.

Reactive Programmig には, 2 つの種類があるように思う.

  • Actor Model
  • Monadic Model

所感

以下の記事がわかりやすい.

最近よくみかける用語だし, これから流行しそうな手法.

GUI, インフラ, ビッグデータ処理など様々な場面で浸透しつつあります. 今までは複雑すぎて作ることが難しかったアプリケーションが簡単に設計できるようになっていくでしょう.

リアクティブ宣言なんという, かっこいい文章も存在する.

Object-Functional Programming (OFP)

オブジェクト指向のパラダイムと関数型のパラダイムの両方を利用して プログラミングする.

上流工程では, 今までどおりオブジェクト指向設計で考えることになる. ユースケースで今までどおり要件定義をして, コンポーネント分割までする. そこから, オブジェクトかファンクションのどちらかつかって責務を実現する. なので, OOP と FP は共存関係にある.

OFP 新三種の神器.

  • トレイト
  • モナド
  • 型クラス

OFP を導入することメリットは, 以下.

  • 高階関数DSL を書くことで 開発効率 をあげる
  • Monadic Programming を行うことで並列処理の品質をあげる

どこに Functional Programming を適用するか?

Functinal Programming で書くと, バグが出にくいので, Functonal Programming の割合をできるだけ増やしていくのがベスト.

システム開発では, OO:FP の割合は 6:4 くらいか??

FP でつくるのに適した部分は, DSL の部分. OOP で, Framework と呼ばれている部分.

アプリ開発は Java でもいい. アプリ開発の基盤にある DSL 部分を 関数型でかく.

DSL

DSL とは,特定のタスク向けに設計されたコンピュータ言語. DSL は一種類のタスクをうまく実行することに集中したもの.

そして, FP (というよりも Scala) は, DSL を書くことに 適している (Scalable language). なぜなら, 簡単に独自の型や制御構造を定義できるので.

まとめ

去年から, 関数型言語をかじりはじめてきたが, 自分が理解してきた

  • Stateless
  • High-order function

という考え方は, いわゆる伝統的な FP の概念だということを知った. また, それにかわるモダンな考え方は Monad だということも知った. (OFP 新三種の神器)

モナドについては, ほとんどまだ理解できていないので, 今年はモナドに注目して学んでいくことにする.

個人的には, 関数型言語を並列処理どう適用するかという話をもう少し つっこんで知りたい. それも, Monadic Model を理解すると見えるかもしれ ない.まずは, Monad.

Next Action

今は (伝統的!) 関数型言語の聖典, SICP を読んでいるので, Monad はさておき, まずはこれを読み終えなければ.

4 月か 9 月に coursera の Scala の講義が開講されたらもう一度受けてみる. (なぜなら, 前回は落第して単位をもらえなかったから…)

Reactive Programming についても学んでみたい. 去年 coursera で講座が 開講されるのをまっていたのだが, 去年は開講されなかった. 今年も開講されなかったら, 11 月からアーカイブ講座をつかって学んで見ようと思う.

24 Jan 2015, 15:23

関数型デザインパターンのプレゼン動画をまとめてみた

はじめに

オブジェクト指向言語の世界では, デザインパターンが人気!

関数型言語の世界でも, OO の影響を受けて, きっと誰かがパターンを考えているに違いないと考えて, いろいろとネットで情報収集してみた.

思ったとおりで, いくつか動画をみつけたのでまとめてみる.

Functinal programming patterns for the non-mathematician

15 分くらいに短くまとまっている動画. JavaScript.

関数に成り立つ法則によってまとめている.

  • Composition laws
  • Lenses laws
  • Fmap laws
  • Monad laws
  • Applicative laws
  • Monoid laws
  • Arrow laws

SlideShare のプレゼン資料

Functional Programming Patterns

動画はリンク先から.

プレゼン, 動画ともにとてもボリュームがある. 導入部の説明がとても笑える.

SlideShare のプレゼン資料

Patterns and Functional Programming

Patterns and Functional Programming from Chariot Solutions on Vimeo.

この本を書いた人の動画.

Amazon:

Pragmatic Bookshelf:

既存の OO Pattern を FP で置き換える.

こんな記事もみつけた.

Replacing Object Oriented Patterns
    Introduction
    Replacing Functional Interface
    Replacing State Carrying Functional Interface
    Replacing Command excerpt
    Replacing Builder For Immutable Object
    Replacing Iterator
    Replacing Template Method
    Replacing Strategy
    Replacing Null Object
    Replacing Decorator
    Replacing Visitor
    Replacing Dependency Injection

FP 独自のパターンも紹介.

Functional Patterns
    Introduction
    Tail Recursion excerpt
    Mutual Recursion
    Filter-Map-Reduce
    Chain of Operations
    Function Builder
    Memoization
    Lazy Sequence
    Focused Mutability
    Customized Control Flow
    Domain-Specific Language

これはあとで読みたい.(できれば日本語訳で!!)

Functional Design Patterns

Clojure による,パターンの紹介.

内容をみていないのだけれども, ブックマークだけしておく.

  • State/Event,
  • Consequences,
  • Accumulator
  • MapReduce,
  • Reduce/Combine,
  • Recursive Expansion,

おわりに

シンフォニーとミニマルミュージック

OO でのパターンと FP のパターンでは, うけるイメージが違った.

OO のパターンからは, 堅牢な構築物のようなイメージを受ける. それは, クラス図で表現されているからかもしれない.

それに対して, FP からは, ミニマルな文様なようなイメージを受ける. 微細なパターンが組み合わさって, 全体をつくるような. FP で言うところのパターンは小さいので, OO でいうところの idiom のようにもとらえられる.

それは, 堅牢な交響曲と, 微細なテクノミュージックのような違いを感じる.

今年の目標は関数型パターンをみにつけること.

去年の目標は, OO のデザインパターンを身につけることが目標だった.

今年は, FP のパターンを身につけることを目標にしよう.

それにしても, FP のパターンは Gof のような教科書が見当たらない.

動画の内容にも言えることだけれども, いろんなひとがそれぞれの意見を持っているような群雄割拠状態.

だれでもいいので, すごい本とか出してこの分野を統一してくれないかなと思ってみたり.