体験を伝える―『ガジェット通信』の考え方

面白いものを探しにいこう 本物を体験し体感しよう 会いたい人に会いに行こう 見たことのないものを見に行こう そしてそれをやわらかくみんなに伝えよう [→ガジェ通についてもっと詳しく] [→ガジェット通信フロアについて]

【関数型言語Haskellの基本】高階関数map,reduceを使って遊んでみた

Haskellの対話型環境で関数プログラミング

プログラミングには「命令型」と「関数型」があって、俺たちが触れてきたのはどうも前者らしいぞ…と耳打ちされたあなた。
でも、両方触れたことがなければ何のことやら…ですよね。

この記事では、「関数型言語」が気になるけれど、学んだことはまったくないという方へ、Haskellの簡単なサンプルコードを使ったエクササイズを提供します。
対話型環境で進めますので、一歩ずつ手ごたえを感じながら学ぶことができますよ。

関数プログラミングの特徴って?

はじめに、Haskellのような、典型的な関数プログラミング言語の特徴をザックリ「ある/なし」で表現してみます。

ある
なし

式(expression)
文(statement)

関数型オブジェクト
boolやintなどのプリミティブ型

永続的なデータ
破壊的代入

これだけでは、よく分からないかもしれません。
以下のCのコードを対象に、命令型言語と関数型言語の違いを見ていきましょう。

#define n 5
int main(){
int i = 0;
int snakes[n] = {5,4,3,2,1};
int flogs[n] = {7,6,1,2,2};

int survivors = 0;
while(i < n){
if(flogs[i] > snakes[i]){
survivors += (flogs[i] – snakes[i]);
}
i++;
}
printf(“%dn”, survivors);
return 0;
}

カエルの配列flogsと、ヘビの配列snakesがあり、5つのグループ0,1,2,3,4に何匹ずつ存在するかを表す配列を定義します。
そして、「各グループ内のヘビはカエルを一匹ずつ食べる」という設定で、生き残るカエルの総数を求められるようプログラムを書きました。

int snakes[n] = {5,4,3,2,1};
int flogs[n] = {7,6,1,2,2};

たとえばsnakes[0]とflogs[0]が、グループ0にいるヘビとカエルの数を表します。
それぞれ’5′と’7′ですから、このグループではヘビがカエルを一匹ずつ食べて、カエルは2匹生き残ります。

int survivors = 0;
while(i < n){
if(flogs[i] > snakes[i]){
survivors += (flogs[i] – snakes[i]);
}
i++;
}

減算で生き残るカエルの数を計算し、survivors変数に加えていきます。
ちなみに、ヘビの数がカエルの数より多い時は0匹となるよう、if文で制御しています。

実行すると、「5」が出力され、5匹のカエルが生き残るとわかります。
このプログラムを上記の「ある/なし」の表と照らしてみましょう。

末尾にセミコロンのあるものは全て代入、出力などの「命令文」ですから、実はこのコード中にある式はwhile文の条件式(i < n)のみ。ほかは全て文にあたります。

さらに、i, sumなどの「プリミティブ型変数」も使わず、while文内の処理のような「破壊的代入」も行わないのです。つまり、上記コードのほとんどの要素はHaskellに「ない」のですね。

どうやって同じ処理を実現するかが気になりますか?上記と同じ機能のプログラムをHaskellで書いてみましょう。

Haskellで書くとこうなる

ここからは、対話型環境を使うことを想定して記述します。
GHCの対話環境であるGHCiで実行するのが一般的ですが、オンラインでも下記サイトなどで実行することができます。

http://ghc.io/

まず、リストを用意します。

let snakes = [5,4,3,2,1]
let flogs = [7,6,1,2,2]

1 2次のページ
CodeIQ MAGAZINEの記事一覧をみる
  • 誤字を発見した方はこちらからご連絡ください。
  • ガジェット通信編集部への情報提供はこちらから
  • 記事内の筆者見解は明示のない限りガジェット通信を代表するものではありません。