F# メモ unit

unit は値を持たないことを表す型で、CやC#でいう void のようなもの。
() は unit である。

> let x = ();;

val x : unit = ()

ignore は非 unit な式を unit に変換する関数。
つまり値を使わないことを明示する関数。

> ignore(2*2);;
val it : unit = ()

> 2*2 |> ignore;;
val it : unit = ()

のように使用できる。

F# メモ 関数

定義

2つの int を引数に取り、その和を返す関数 add は以下のように表す。

> let add a b = a + b;;

val add : int -> int -> int

実行してみる。

> add 1 2;;
val it : int = 3

関数の型

float -> int は 「float を引数に取り、int を返す関数」と読む。
上の add の場合 int -> int -> int が関数の型で、「intを引数に取り、「intを引数に取り、intを返す関数」を返す関数」と読む。


型推論

上の add 関数のように引数の型が複数考えられるとき、最初に使用されたときの引数を基に関数の型が決まる。(ただし、対話モードでは一旦 ;; で終了した時点で確定する)

> add 1.0 2.0;;

  add 1.0 2.0;;
  ----^^^

stdin(3,5): error FS0001: This expression was expected to have type
    int    
but here has type
    float

のように float を引数とすることはできない。
これは関数 add が int -> int -> int と推論されているため。
float のみを渡せるようにするには、以下のように明示的に型を指定する。

> let addf (a:float) b = a + b;;

val addf : float -> float -> float

> addf 1.0 2.0;;
val it : float = 3.0

ジェネリック関数

‘a のように ‘ を付けた型を指定すると、どんな型でも引数に取ることができる関数を作ることができる。
‘a でも ‘b でも ‘asdfghjk でもいいらしい。

> let str (x:'a) = x.ToString();;

val str : 'a -> string

> str(10);;
val it : string = "10"

スコープ

F#のスコープはインデントで表される。
全くインデントされていないスコープがモジュールスコープ。

> let Pow2 x =
    let value = x * x
    value;;

val Pow2 : int -> int

> Pow2 10;;
val it : int = 100

関数スコープの最後に評価された値がその関数の戻り値となる。

F# メモ 基本演算子

算術演算子

説明不要ですね。

演算子 意味
+ 加算
減算
* 乗算
/ 除算
** 冪算
% 剰余

数学関数

演算子ではありませんが、基本的なものなので。

関数 意味
abs 絶対値を求める
ceil 整数に丸める(大きい方に)
exp eの引数乗を求める
floor 整数に丸める(小さい方に)
sign 符号を求める(-1, 0 or 1)
log 自然対数を求める
log10 常用対数を求める
sqrt 平方根を求める
cos コサインを求める
sin サインを求める
tan タンジェントを求める
pown 整数の累乗を求める

型変換

型名がそのまま変換関数のように機能する。

> int64 1234.5678;;

val it : int64 = 1234L

ビット演算子

ちょっと特殊。

演算子 意味
&&& AND
||| OR
^^^ XOR
<<< 左シフト
>>> 右シフト

要素へのアクセス

配列や文字列の要素にアクセスする場合は .[] を使用する。
慣れていないうちは . を忘れやすい。

> let str = "abc";;

val str : string = "abc"

> str.[1];;
val it : char = 'b'

論理演算

演算子 意味
&& AND true && false = false
|| OR true || false = true
not NOT not false = true

比較演算

値同士の比較を行い、bool 値を返す。

演算子 意味
< より小さいか
<= 以下か
> より大きいか
>= 以上か
= 同じか
<> 異なるか

compare (関数?) は第一引数の方が小さいときは -1、大きいときは 1、同じなら 0 を返す。

F# メモ 基本型

数値型

F#型名 サフィックス .NET型
byte uy System.Byte
sbyte y System.SByte
int16 s System.Int16
uint16 us System.UInt16
int, int32 System.Int32
uint, uint32 u System.UInt32
int64 L System.Int64
uint64 UL System.UInt64
float System.Double
float32 f System.Float
decimal M System.Decimal

サフィックスは数値の直後に付ける文字。
整数値のデフォルトは int 、小数値のデフォルトは float。

F#の数値リテラルはデフォルトでは10進表記だが、
プレフィックスによって2進、8進、16進として扱える。

進数 プレフィックス
10進
2進 0b
8進 0o
16進 0x

多倍長整数

その名の通り、64ビットを超える巨大な整数も扱えるようになる。

F#型名 サフィックス .NET型
bigint I System.Numerics.BigInteger

文字

文字型はcharで内部的にはUTF-16の値を保持している。
つまり2バイト。

文字リテラルは ‘a’ のようにアポストロフィーで囲む。

一部の文字はエスケープシーケンスで表す。

文字 文字の意味
\’ アポストロフィ
\” ダブルクオーツ
\\ バックスラッシュ
\b バックスペース
\n LF
\r CR
\t 水平タブ

文字列

型名は string で、リテラルは “abc” のようにダブルクオーツで囲む。

> let s1 = "any string";;

val s1 : string = "any string""

コード上で改行を含んでも構わない。

> let s2 = "line1
            line2
            line3"
;;

val s2 : string = "line1
            line2
            line3"

コード上でのみ改行する場合。
行末にバックスラッシュで、改行と続く空白文字が無視される。

> let s3 = "line1-\
            continue-\
            last"
;;

val s3 : string = "line1-continue-last"

文字列リテラルに B サフィックスを追加することで byte 配列に変換される。
byte に格納できない文字が含まれているとエラーになるので注意。

> let str = "test"B;;

val str : byte [] = [|116uy; 101uy; 115uy; 116uy|]

ブール値

型名は bool で、.NET型名は System.Boolean
true (真)か false (偽)のどちらかを持つ。

Programming F#

とにかくF#の日本語の書籍がないので、Programming F# を買いました。
英語なので読むのに多少時間はかかりますが、現時点ではこれが一番分かりやすいかと。

気が向いたらまとめてみようと思います。

F# メモ Hello World

Hello, World プログラム

なにはともあれ、ハローワールドを書かないと話は進みません。

printfn "Hello, World"

コンパイルする場合はこれで良いのですが、インタプリタで実行する場合は行末に ;; が必要。


シンプルな関数を作成する

let Cube x = x * x * x

printfn "%d" (Cube 8)

1行目で3乗の値を返す関数を作っています。


複数のソースファイルをコンパイルする

Visual Studioで複数のファイルを作ってコンパイルし、実行すると、上から順に実行されます。
上からというのはソリューションエクスプローラで表示されている順ということです。
この順番はAlt+↑、Alt+↓で変更できます。

TOP

INFORMATION

未来の自分のためのメモ
管理者:rei