F#入門 Beta版

net-kのF#入門サイトにようこそ!

あなたは 人目のお客様です。

更新履歴

最終更新日:2009/09/01 3:27:00

更新履歴

目次

はじめに

当サイトは、F#について独自に調査した内容をまとめたものです。

私自身まだまだF#を勉強中の身なので、内容の正確さは保証できませんのでご了承ください。 (もちろん、なるべく正確なものにしようと思っています。ご意見、ご指摘等はありがたく頂戴致します。)


また、当サイトは作成途中のものであり、これからもっと情報を増やしていき、説明の方もわかり易く正確なもの(※1)にしていこうと思います。

※1 現時点でも直したいところがいくつもあるのですが、更新の方がちょっと間に合ってません。


F#の導入

F#の概要と、開発環境について説明します

F#とは?

Microsoft が研究開発中の関数型プログラミング言語

F#の特長


他多数

※本家サイトでは、さまざまな特長が紹介されています


インストール方法


下記よりインストーラーがダウンロードできます。

http://research.microsoft.com/fsharp/fsharp.aspx

使い方

コンパイルして実行ファイル生成

> fsc sample.f


実行ファイルができます

ライブラリをリンクして実行ファイル生成

> fsc Winform.fs -r System.Windows.Forms.dll


対話環境

一文ずつ実行することができます。

対話環境立ち上げます。
コマンドプロンプトよりfsiを実行してください。

> fsi


試しに、1 + 1の式を評価(実行)してみる。

> 1 + 1;;
val it : int = 2


文法解説

ここからはF#の文法を説明します。

F#は関数型プログラミングを基調とした、最新のマルチパラダイムプログラミング言語です。
具体的には、関数型、手続き型、オブジェクト指向型のプログラミングパラダイムとなります。

基本的には、これらのプログラミングパラダイムごとに解説していきます。

そして、基本的な文法の解説を終えた後、さらに高度な機能について説明しようと思います。


関数型プログラミング

関数型プログラミング

命令型プログラミング

命令型プログラミング

ジェネリックプログラミング

ジェネリックプログラミング

オブジェクト指向型プログラミング

オブジェクト指向型プログラミング

言語指向型プログラミング

言語指向型プログラミング

その他の機能

F#は最新のプログラミング言語ということもあり、高度な機能がたくさん搭載されています。そのうちのいくつかを紹介します

モジュール

モジュールは独立した機能を持ったソフトウェア部品です。

なぜ、モジュールのようなものが必要かというと、 ソフトウェアを独立した機能に分けて開発することは重要だから です。 これをうまくやるのと、そうでないのでは、品質や生産性が大き く変わります。

開発手法はいろいろありますが、基本的には論理的に大きな 単位からソフトウェアを設計します。 アーキテクチャを決定し 、プログラム実装のフェーズに近づくと、プログラムをどのよう なモジュールに分割するかということを考えることになります。

また、開発中にプログラムに論理的な共通点を見つけ、 モジュールとしてまとめるということもあるでしょう。

それでは、具体的にF#でどのようにモジュール分けしていく か見ていきましょう。

四則演算をする関数(sum,sub,mul,div)を定義し、それを四則演算モジュール(MyLibrary.MyModule)としてまとめます。
#light
module MyLibrary.MyModule

let sum x y = x + y
let sub x y = x - y
let mul x y = x * y
let div x y = x / y

ライブラリをコンパイルします

fsc -a my_module.fs
※-a オプションは、ライブラリをビルドするオプションです。

この四則演算モジュールを利用するプログラムを書いてみます

#light
open MyLibrary.MyModule

printfn "sum %d %d = %d " 4 2 (sum 4 2)
printfn "sub %d %d = %d " 4 2 (sub 4 2)
printfn "mul %d %d = %d " 4 2 (mul 4 2)
printfn "div %d %d = %d " 4 2 (div 4 2)

このプログラムをコンパイルして実行します
fsc use_my_module.fs -o use_my_module -r my_module.dll
※-r でモジュールの定義されたライブラリをロードします。

実行結果
sum 4 2 = 6
sub 4 2 = 2
mul 4 2 = 8
div 4 2 = 2

拡張メソッド

既存の型を変更、再コンパイルすることなく、メソッド(関数)を追加することができます。

拡張メソッドを定義する方法は、モジュールに追加したいメソッドを定義して、追加したい型のメンバにモジュールに定義したメソッドを指定します。

定義した拡張メソッドの使い方ですが、モジュールをopenすれば、既存の型から拡張メソッドを呼び出すことができます。

具体例として、整数型に自身が7の倍数か判定するメソッドを追加してみます。

■サンプル

#light

// 整数型を拡張する。
module ExtendInteger =
    let IsMultiOfSeven(i) =
        if i % 7 = 0 then true else false

    type System.Int32 with
        member i.IsMultiOfSeven = IsMultiOfSeven(i)

open ExtendInteger

printfn "数値を入力してください。"
let num = System.Int32.Parse( System.Console.ReadLine() ) 

if num.IsMultiOfSeven = true 
    then printfn "7の倍数です。"
    else printfn "7の倍数ではありません。"

■実行結果

// まずは7の倍数でない数値を入力してみる
数値を入力してください。
12
7の倍数ではありません。

// 今度は7の倍数を入力してみる
数値を入力してください。
21
7の倍数です。

パイプライン演算子

パイプライン演算子は中間演算子で、左項の値を右項の関数に引数渡しします

下記にかんたんなサンプルを示します

> let add x y = x + y;;
val add : int -> (int -> int)
> let add_1 = 1 |> add;;
val add_1 : (int -> int)
> 2 |> add_1;;
val it : int = 3

非同期ワークフロー

マルチコアCPUの普及が進む中、今後非同期処理はますます重要になることが予想されます。 しかし、現在のメジャーなプログラミング言語は、言語仕様として非同期処理をサポートしていません。 複雑なスレッドAPIなどを利用して、非同期処理を書いていく必要があり、敷居の高いものとなっていました。

そんな中、F#は非同期ワークフローを用いて、非同期処理をとても簡単かつスマートに書くことができます。 非同期処理に精通していないプログラマでも、十分に使いこなすことができるでしょう。

それでは、F#の非同期処理の世界を紹介させていただきます。

async識別子

async
{
	非同期で実行したい処理

   (オプションで return )
}
このasyncで作られた非同期処理のことを"asynchronous computation"という。 return は、asyncで実行した非同期処理の結果を返すことができ。 結果を受け取るには、let!オペレータ使えばいい。

let! オペレーター

let! = "asynchronous computation"

asynchronous computationを実行して、結果を待つ。 その後、必要ならワークフロー(処理)を停止して、イベントがコールバックとして返ってってくるのを待っている



それでは、いくつかサンプルを紹介しましょう。

#light

let task1 = async { while true do printf "a" }
let task2 = async { while true do printf "b" }

Async.Run (Async.Parallel [task1; task2] )
このサンプルに使われている関数の説明
Aync.Parallel
非同期実行するasynchronous computationを指定する(それぞれスレッドプールに割り当てられる。
Async.Run

asynchronous computationを実行する。

実行結果
aaaaaaaa.......bbbbbbbbbbbb.............aaaaaaaaaaa...bbbbb

いつくかのa と bが出力されつづけます。この出力からスレッドが切り替わっていることがわかります。 (切り替わってないとwhileが中断されることはないからです)

※a と bはかなりの数出力されるので、.で省略しています。実際に.は表示されません。

Aync.Runは、非同期処理(スレッド)を実行し、その終了を待ちます。 つまり、終了する前で、Aync.Runを実行したスレッドは何もすることができません。

次のサンプルは、非同期処理を実行しますが、その終了を待たずに非同期処理実行したスレッドの処理を継続します

#light

let task1 = async { while true do printf "a" }

Async.Spawn task1

while true do printf "c"

このサンプルに使われている関数の説明
Async.Spawn

asynchronous computationを実行する。 Async.Runとは違い、結果が返ってくるのは待たない。

実行結果
aaaaaaaaa.......cccccccccccccccccccccc.....aaaaaaaaaa........

いくつかのa と cが出力され続けます。 c を出力していることから、非同期処理を実行後、停止していないことがわかります。

今後の予定

当面は、自分以外の人の役に立つレベルまでサイトが充実することを目指そうと思います
ゆくゆくは最新の情報なども扱いたいと思っています。

参考

Microsoft Research F#
http://research.microsoft.com/fsharp/fsharp.aspx

Microsoft F# Developer Center
http://msdn.microsoft.com/en-us/fsharp/default.aspx

連絡先

mail to net.kazu@gmail.com

返信は私の可能な限りの対応となってしまいますが、御容赦ください。
なお、F#や当サイトに関連したメールのみご送信ください。

ブログ

ピコピコの日記
http://d.hatena.ne.jp/net-k/

BBS

F#入門 BBS
http://entry-fsharp.bbs.fc2.com

Copyright (C) 2008 net-k All Rights Reserved.

inserted by FC2 system