基本的な関数の作り方(Haskell)
この記事では、関数の基本的な作り方について学びます。
Haskellには関数にまつわる概念がたくさんあります。再帰関数や高階関数など難しいトピックは除いて、ここでは「基本の関数」の作り方を紹介します。
関数とは何か?
データを投入すると、何らかの処理をして、結果を返却する仕組みです。 部品として処理を1まとめにすることで、より見やすく効率的にコードが書けます。
関数で重要な概念が3つあります。引数、戻り値、仮引数です。
- 引数:外部から投入する値のこと
→ 関数に対して色々なデータを処理させられる - 戻り値:処理の結果として返却される値のこと
→ 計算結果の値をまた別の場所で再利用できる - 仮引数:それが定義された関数の中だけで使う一時的な変数のこと
→ 引数として外部から投入する値を受け取るために使われる
Haskellにおける「関数」の特徴
その中でもHaskellの関数は大きく3つの特徴を持っています。
1、全ての式が値をもつ
2、全ての関数が引数・戻り値を持つ
3、どんな時でも常に同じ値を返す
まるでサッカーのパス回しのように、関数同士が戻り値を返却し合います。関数同士による戻り値のやり取りによって、プログラムを組み立てるのがHaskellのスタイルです。
また式の値は増減したり途中で変わることはありません。プログラムの堅牢性を保つため、どんな時でも常に同じ値を返すことを期待されます。これを難しい言葉で参照透過性を持つ..と呼びます。
関数の定義
関数の定義はこちらです。
関数名 :: 引数 -> 戻り値
関数名 引数
= 処理内容
命令型言語の関数と違って、すごくサッパリと記述していますよね。{ }
などもないので初見の方は混乱しがちですが、結局していることは一緒です。
関数の作り方
受け取った数値を2倍にするnibai
関数を例に作り方を学んでいきます。1番下の行にあるmain = print (nibai 10)
では、nibai関数へ10という数値を渡しています。結果としては20という数値が返却されます。
nibai :: Int -> Int --1行目
nibai num --2行目
= num * 2 --3行目
main = print (nibai 10)
ここで注目して頂きたいのは上から3行の部分です。この部分で関数を作成しており、3つの内容を決めています。
1行目:引数、戻り値のデータ型はどうするか?
2行目:関数名、仮引数名はどうするか?
3行目:処理内容はどうするか?
1、引数、戻り値のデータ型はどうするか?
1行目では引数、戻り値のデータ型を指定しています。関数名の後に::
(型宣言)を書きます。その後に矢印->
で区切って、データ型を指定します。
nibai :: Int -> Int --1行目
nibai num --2行目
= num * 2 --3行目
引数と戻り値が区別されないのでややこしいですよね。これは常に引数を1つだけ受け取るためです。左の引数を1つ受け取る→右のモノ(関数or値)を返却..を繰り返します。(関数を戻り値として返せるのもHaskellの大きな特徴でしたね!)。同時に受け取る引数を1つにすることで、仕組みをシンプルに保つことができます。
ややこしい話をしましたが、ここではもっとカンタンに考えます。戻り値は1つしかないので、1番最後に書かれたデータ型が戻り値です。それより手前が引数のデータ型となります。 今回の引数は1つなので、Intは戻り値用・引数用で2つ書けばOKです。
引数・戻り値のデータ型はHaskellのプログラムが自動的に補足してくれます。分かりきったモノは書かなくてもOKですし、コンパクトに関数を記述できるのですごく便利です。
2、関数名、仮引数名はどうするか?
2行目では関数名、仮引数名を決めています。関数は必ず引数を持つので仮引数名を決める必要があります。
nibai :: Int -> Int --1行目
nibai num --2行目
= num * 2 --3行目
ここでは関数名をnibai
、仮引数名をnum
としました。1番最初は絶対に関数名となるので、それ以後が仮引数となります。今回の引数は1つなので、それを受け取る仮引数も1つです。
3、処理内容はどうするか?
3行目では(=の後に続けて)処理内容を決めています。改行しなくてもOKですが、改行した場合はインデントを入れるのを忘れないで下さい。今回は単純にnum
の数値を2倍にしています。
nibai :: Int -> Int --1行目
nibai num --2行目
= num * 2 --3行目
戻り値はどうなるのでしょうか?命令型言語の場合はreturn
などで明確に戻り値を定義していましたよね。
Haskellの場合、=
の後に式(値を返却するモノ)を書きます。式に属するモノは、変数、関数、真偽値、計算式..などがあります。なので=
の後の処理内容としては、(今回のように計算式であっても)値を返却するモノであれば何でもOKです。
関数呼び出し
最後の行で関数呼び出しを行なっています。関数を呼び出すには定義するときと同じです。関数名と引数を空白で並べて書きます。ここでは10
という数値を引数として渡しています。
nibai :: Int -> Int
nibai num
= num * 2
main = print (nibai 10) --関数呼び出し
nibai 10
によって関数を呼び出し、それをprint
関数でそのまま出力にかけている..というわけです。
※)複数の引数の渡し方についてはこちらの記事をどうぞ
Discussion