F# での関数の使用

単純な関数定義は、次のようになります。

let f x = x + 1

この例では、関数の名前は f、引数は x、引数の型は int、関数本体は x + 1、戻り値の型は int です。

F# を特徴付ける特性に、関数が最大のステータスを持つことがあります。 他の組み込み型の値で実行できる処理はすべて、同等の手間で、関数を使用して実行できます。

  • 関数の値に名前を指定できます。

  • リストなどのデータ構造に関数を格納できます。

  • 関数呼び出しの引数として関数を渡すことができます。

  • 関数呼び出しから関数を返すことができます。

値に名前を付ける

関数がファースト クラスの値である場合は、整数や文字列、その他の組み込みの型に名前を付けることができるのと同様に、関数に名前を付けることができる必要があります。 関数型プログラミングの記述では、これを "値に識別子を束縛する" と表現しています。 F# では、let バインドを使用して、名前を値にバインドします: let <identifier> = <value>。 次に、2 つのコード例を示します。

// Integer and string.
let num = 10
let str = "F#"

関数には簡単に名前を付けることができます。 次の例では、識別子 squareItラムダ式fun n -> n * n にバインドすることにより、squareIt という名前の関数を定義します。 関数 squareIt は、1 つのパラメーター n を受け取り、このパラメーターの 2 乗を返します。

let squareIt = fun n -> n * n

F# では、次に示すより簡潔な構文が用意されており、少量の入力で同じ結果を得ることができます。

let squareIt2 n = n * n

以降の例では、関数の宣言と他の型の値の宣言の類似性を強調するために、ほとんどの場合に最初の let <function-name> = <lambda-expression> というスタイルを使用しています。 ただし、名前付き関数はすべて、簡潔な構文で記述することもできます。 一部の例では、両方の方法を使用して記述しています。

値をデータ構造に格納する

ファースト クラスの値はデータ構造に格納できます。 次のコード例では、リストとタプルに値を格納する方法を示しています。

// Lists.

// Storing integers and strings.
let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
let stringList = [ "one"; "two"; "three" ]

// You cannot mix types in a list. The following declaration causes a
// type-mismatch compiler error.
//let failedList = [ 5; "six" ]

// In F#, functions can be stored in a list, as long as the functions
// have the same signature.

// Function doubleIt has the same signature as squareIt, declared previously.
//let squareIt = fun n -> n * n
let doubleIt = fun n -> 2 * n

// Functions squareIt and doubleIt can be stored together in a list.
let funList = [ squareIt; doubleIt ]

// Function squareIt cannot be stored in a list together with a function
// that has a different signature, such as the following body mass
// index (BMI) calculator.
let BMICalculator = fun ht wt ->
                    (float wt / float (squareIt ht)) * 703.0

// The following expression causes a type-mismatch compiler error.
//let failedFunList = [ squareIt; BMICalculator ]


// Tuples.

// Integers and strings.
let integerTuple = ( 1, -7 )
let stringTuple = ( "one", "two", "three" )

// A tuple does not require its elements to be of the same type.
let mixedTuple = ( 1, "two", 3.3 )

// Similarly, function elements in tuples can have different signatures.
let funTuple = ( squareIt, BMICalculator )

// Functions can be mixed with integers, strings, and other types in
// a tuple. Identifier num was declared previously.
//let num = 10
let moreMixedTuple = ( num, "two", 3.3, squareIt )

タプルに格納された関数名が実際に関数として評価されることを確認するために、次の例では、fst 演算子と snd 演算子を使用して、funAndArgTuple タプルから 1 番目の要素と 2 番目の要素を抽出します。 タプルの 1 番目の要素は squareIt、2 番目の要素は num です。 識別子 num は、前の例で整数 10 にバインドされています。これは、squareIt 関数の有効な引数です。 2 番目の式は、タプルの 1 番目の要素をタプルの 2 番目の要素に適用します。つまり、squareIt num となります。

// You can pull a function out of a tuple and apply it. Both squareIt and num
// were defined previously.
let funAndArgTuple = (squareIt, num)

// The following expression applies squareIt to num, returns 100, and
// then displays 100.
System.Console.WriteLine((fst funAndArgTuple)(snd funAndArgTuple))

識別子 num と整数 10 を入れ替えて使用できるのと同様に、識別子 squareIt とラムダ式 fun n -> n * n も入れ替えて使用できます。

// Make a tuple of values instead of identifiers.
let funAndArgTuple2 = ((fun n -> n * n), 10)

// The following expression applies a squaring function to 10, returns
// 100, and then displays 100.
System.Console.WriteLine((fst funAndArgTuple2)(snd funAndArgTuple2))

値を引数として渡す

値が言語内でファースト クラスのステータスを持つ場合、その値は関数に引数として渡すことができます。 たとえば、整数や文字列を引数として渡すのは一般的です。 次のコードは、F# で引数として渡される整数や文字列を示しています。

// An integer is passed to squareIt. Both squareIt and num are defined in
// previous examples.
//let num = 10
//let squareIt = fun n -> n * n
System.Console.WriteLine(squareIt num)

// String.
// Function repeatString concatenates a string with itself.
let repeatString = fun s -> s + s

// A string is passed to repeatString. HelloHello is returned and displayed.
let greeting = "Hello"
System.Console.WriteLine(repeatString greeting)

関数がファースト クラスのステータスを持つ場合は、同様の方法で関数を引数として渡すことができる必要があります。 これは高階関数の 1 番目の特性です。

次の例で、applyIt 関数は 2 つのパラメーター oparg を持っています。 1 つのパラメーターを持つ関数を op に指定し、その関数の適切な引数を arg に渡すと、oparg に適用した結果が返されます。 次の例では、関数の引数と整数の引数の両方が、同じように名前を使用して渡されています。

// Define the function, again using lambda expression syntax.
let applyIt = fun op arg -> op arg

// Send squareIt for the function, op, and num for the argument you want to
// apply squareIt to, arg. Both squareIt and num are defined in previous
// examples. The result returned and displayed is 100.
System.Console.WriteLine(applyIt squareIt num)

// The following expression shows the concise syntax for the previous function
// definition.
let applyIt2 op arg = op arg
// The following line also displays 100.
System.Console.WriteLine(applyIt2 squareIt num)

関数を引数として他の関数に送信できる機能は、マップ操作やフィルター操作など、関数型プログラミング言語に共通の抽象化が基礎になっています。 たとえば、マップ操作は、複数の関数で共有される計算を引き受ける高階関数であり、リストを走査し、各要素に対してなんらかの処理を実行し、結果のリストを返します。 整数のリストの各要素をインクリメントしたり、各要素を 2 乗したり、文字列のリストの各要素を大文字に変更したりできます。 計算のエラーが発生しやすい部分は、リストを走査し、返す結果のリストを構築する再帰プロセスです。 この部分はマッピング関数に取り込まれます。 特定のアプリケーションで記述する必要があるのは、各リスト要素に個別に適用する関数 (加算、2 乗、大文字と小文字の変更) だけです。 その関数は、前の例で squareItapplyIt に渡されたように、マッピング関数への引数として渡されます。

F# では、リスト配列シーケンスなど、ほとんどのコレクション型にマップ メソッドが用意されています。 次の例では、リストを使用しています。 構文は List.map <the function> <the list> です。

// List integerList was defined previously:
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]

// You can send the function argument by name, if an appropriate function
// is available. The following expression uses squareIt.
let squareAll = List.map squareIt integerList

// The following line displays [1; 4; 9; 16; 25; 36; 49]
printfn "%A" squareAll

// Or you can define the action to apply to each list element inline.
// For example, no function that tests for even integers has been defined,
// so the following expression defines the appropriate function inline.
// The function returns true if n is even; otherwise it returns false.
let evenOrNot = List.map (fun n -> n % 2 = 0) integerList

// The following line displays [false; true; false; true; false; true; false]
printfn "%A" evenOrNot

詳細については、「リスト」を参照してください。

関数呼び出しの結果値を返す

最後に、関数が言語内でファースト クラスのステータスを持つ場合は、整数や文字列などの型を返す場合と同様に、その関数を関数呼び出しの結果値として返すことができる必要があります。

次の関数呼び出しでは、整数を返してそれらを表示します。

// Function doubleIt is defined in a previous example.
//let doubleIt = fun n -> 2 * n
System.Console.WriteLine(doubleIt 3)
System.Console.WriteLine(squareIt 4)

次の関数呼び出しでは、文字列を返します。

// str is defined in a previous section.
//let str = "F#"
let lowercase = str.ToLower()

次の関数呼び出しはインラインで宣言されており、ブール値を返します。 表示される値は True です。

System.Console.WriteLine((fun n -> n % 2 = 1) 15)

関数呼び出しの結果値として関数を返すことができるのは、高階関数のもう 1 つの特徴です。 次の例では、1 つの引数 checkFor を受け取り、結果値として新しい関数を返す item という関数を定義します。 返された関数は、引数 lst としてリストを受け取り、その item 内で lst を検索します。 item が存在する場合、関数は true を返します。 item がない場合、関数は false を返します。 次のコードでは、前のセクションと同様に、用意されているリスト関数 List.exists を使用してリストを検索します。

let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

次のコードでは、checkFor を使用して新しい関数を作成します。作成された関数は、1 つの引数としてリストを受け取り、そのリストから 7 を検索します。

// integerList and stringList were defined earlier.
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
//let stringList = [ "one"; "two"; "three" ]

// The returned function is given the name checkFor7.
let checkFor7 = checkFor 7

// The result displayed when checkFor7 is applied to integerList is True.
System.Console.WriteLine(checkFor7 integerList)

// The following code repeats the process for "seven" in stringList.
let checkForSeven = checkFor "seven"

// The result displayed is False.
System.Console.WriteLine(checkForSeven stringList)

次の例では、F# における関数のファースト クラスのステータスを使用して、2 つの関数の引数の合成を返す compose 関数を宣言します。

// Function compose takes two arguments. Each argument is a function
// that takes one argument of the same type. The following declaration
// uses lambda expression syntax.
let compose =
    fun op1 op2 ->
        fun n ->
            op1 (op2 n)

// To clarify what you are returning, use a nested let expression:
let compose2 =
    fun op1 op2 ->
        // Use a let expression to build the function that will be returned.
        let funToReturn = fun n ->
                            op1 (op2 n)
        // Then just return it.
        funToReturn

// Or, integrating the more concise syntax:
let compose3 op1 op2 =
    let funToReturn = fun n ->
                        op1 (op2 n)
    funToReturn

注意

さらに短いコードについては、次の「カリー化関数」のセクションを参照してください。

次のコードでは、2 つの関数を compose の引数として渡します。どちらの関数も、同じ型の 1 つの引数を受け取ります。 戻り値は、この 2 つの関数の引数の合成である新しい関数です。

// Functions squareIt and doubleIt were defined in a previous example.
let doubleAndSquare = compose squareIt doubleIt
// The following expression doubles 3, squares 6, and returns and
// displays 36.
System.Console.WriteLine(doubleAndSquare 3)

let squareAndDouble = compose doubleIt squareIt
// The following expression squares 3, doubles 9, returns 18, and
// then displays 18.
System.Console.WriteLine(squareAndDouble 3)

注意

F# には、関数を合成する演算子として、<<>> の 2 つが用意されています。 たとえば、let squareAndDouble2 = doubleIt << squareIt は、前の例の let squareAndDouble = compose doubleIt squareIt と同じです。

次に、関数呼び出しの結果値として関数を返し、単純な推測ゲームを作成する例を示します。 ゲームを作成するには、他者に推測してもらう値を makeGame に渡して target を呼び出します。 makeGame 関数からの戻り値は、1 つの引数 (推測) を受け取ってその推測が正しいかどうかを報告する関数です。

let makeGame target =
    // Build a lambda expression that is the function that plays the game.
    let game = fun guess ->
                   if guess = target then
                      System.Console.WriteLine("You win!")
                   else
                      System.Console.WriteLine("Wrong. Try again.")
    // Now just return it.
    game

次のコードでは、makeGame に値 7 を渡して target を呼び出します。 識別子 playGame には、返されたラムダ式がバインドされます。 したがって、playGame は、guess の値を 1 つの引数として受け取る関数になります。

let playGame = makeGame 7
// Send in some guesses.
playGame 2
playGame 9
playGame 7

// Output:
// Wrong. Try again.
// Wrong. Try again.
// You win!

// The following game specifies a character instead of an integer for target.
let alphaGame = makeGame 'q'
alphaGame 'c'
alphaGame 'r'
alphaGame 'j'
alphaGame 'q'

// Output:
// Wrong. Try again.
// Wrong. Try again.
// Wrong. Try again.
// You win!

カリー化関数

前のセクションで示した例の多くは、F# の関数宣言で暗黙的な "カリー化" を利用することで、より簡潔に記述できます。 カリー化とは、複数のパラメーターを持つ関数を、それぞれが単一のパラメーターを持つ一連の埋め込み関数に変換するプロセスです。 F# では、複数のパラメーターを持つ関数は本質的にカリー化されます。 たとえば、前のセクションの compose は、次に示すように、3 つのパラメーターを使用する簡潔なスタイルで記述できます。

let compose4 op1 op2 n = op1 (op2 n)

ただし、compose4curried に示すように、この結果は 1 つのパラメーターを持つ関数で、その関数もパラメーターが 1 つの関数を返し、さらにその関数も、パラメーターが 1 つの別の関数を返します。

let compose4curried =
    fun op1 ->
        fun op2 ->
            fun n -> op1 (op2 n)

この関数は、いくつかの方法で呼び出すことができます。 次のそれぞれの例は、18 を返して表示します。 どの例でも、compose4compose4curried に置き換えることができます。

// Access one layer at a time.
System.Console.WriteLine(((compose4 doubleIt) squareIt) 3)

// Access as in the original compose examples, sending arguments for
// op1 and op2, then applying the resulting function to a value.
System.Console.WriteLine((compose4 doubleIt squareIt) 3)

// Access by sending all three arguments at the same time.
System.Console.WriteLine(compose4 doubleIt squareIt 3)

置き換える前と同じように関数が機能することを確認するには、元のテスト ケースをもう一度試します。

let doubleAndSquare4 = compose4 squareIt doubleIt
// The following expression returns and displays 36.
System.Console.WriteLine(doubleAndSquare4 3)

let squareAndDouble4 = compose4 doubleIt squareIt
// The following expression returns and displays 18.
System.Console.WriteLine(squareAndDouble4 3)

注意

パラメーターをタプルとして囲むことで、カリー化を制限できます。 詳細については、「パラメーターと引数」の「パラメーターのパターン」を参照してください。

次の例では、暗黙的なカリー化を使用して、より短いバージョンの makeGame を作成します。 この形式では、makeGamegame 関数を作成して返す方法の詳細はそれほど明確ではありませんが、同じ結果を返す元のテスト ケースを使用することで確認できます。

let makeGame2 target guess =
    if guess = target then
       System.Console.WriteLine("You win!")
    else
       System.Console.WriteLine("Wrong. Try again.")

let playGame2 = makeGame2 7
playGame2 2
playGame2 9
playGame2 7

let alphaGame2 = makeGame2 'q'
alphaGame2 'c'
alphaGame2 'r'
alphaGame2 'j'
alphaGame2 'q'

カリー化の詳細については、「関数」の「引数の部分適用」を参照してください。

識別子と関数定義の交換可能性

前に示した例において、変数名 num は整数 10 に評価されます。したがって、num が有効な場所では、当然ながら 10 も有効です。 関数識別子とその値にも、同じことが当てはまります。つまり、関数名を使用できる場所では、その名前にバインドされているラムダ式も使用できます。

次の例では、Boolean と呼ばれる isNegative 関数を定義し、この関数の名前と関数の定義を同じように使用します。 次の 3 つの例は、すべて False を返して表示します。

let isNegative = fun n -> n < 0

// This example uses the names of the function argument and the integer
// argument. Identifier num is defined in a previous example.
//let num = 10
System.Console.WriteLine(applyIt isNegative num)

// This example substitutes the value that num is bound to for num, and the
// value that isNegative is bound to for isNegative.
System.Console.WriteLine(applyIt (fun n -> n < 0) 10)

もう 1 歩進めて、applyIt にバインドされている値を applyIt の代わりに使用します。

System.Console.WriteLine((fun op arg -> op arg) (fun n -> n < 0)  10)

F# におけるファースト クラスの値としての関数

前のセクションの各例は、F# の関数が、ファースト クラスの値であるための基準を満たしていることを示しています。

  • 関数定義に識別子をバインドできます。
let squareIt = fun n -> n * n
  • 関数をデータ構造に格納できます。
let funTuple2 = ( BMICalculator, fun n -> n * n )
  • 関数を引数として渡すことができます。
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
  • 関数を関数呼び出しの結果値として返すことができます。
let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

F# の詳細については、「F# 言語リファレンス」を参照してください。

説明

次のコードには、このトピックのすべての例が含まれています。

コード

// ** GIVE THE VALUE A NAME **


// Integer and string.
let num = 10
let str = "F#"



let squareIt = fun n -> n * n



let squareIt2 n = n * n



// ** STORE THE VALUE IN A DATA STRUCTURE **


// Lists.

// Storing integers and strings.
let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
let stringList = [ "one"; "two"; "three" ]

// You cannot mix types in a list. The following declaration causes a
// type-mismatch compiler error.
//let failedList = [ 5; "six" ]

// In F#, functions can be stored in a list, as long as the functions
// have the same signature.

// Function doubleIt has the same signature as squareIt, declared previously.
//let squareIt = fun n -> n * n
let doubleIt = fun n -> 2 * n

// Functions squareIt and doubleIt can be stored together in a list.
let funList = [ squareIt; doubleIt ]

// Function squareIt cannot be stored in a list together with a function
// that has a different signature, such as the following body mass
// index (BMI) calculator.
let BMICalculator = fun ht wt ->
                    (float wt / float (squareIt ht)) * 703.0

// The following expression causes a type-mismatch compiler error.
//let failedFunList = [ squareIt; BMICalculator ]


// Tuples.

// Integers and strings.
let integerTuple = ( 1, -7 )
let stringTuple = ( "one", "two", "three" )

// A tuple does not require its elements to be of the same type.
let mixedTuple = ( 1, "two", 3.3 )

// Similarly, function elements in tuples can have different signatures.
let funTuple = ( squareIt, BMICalculator )

// Functions can be mixed with integers, strings, and other types in
// a tuple. Identifier num was declared previously.
//let num = 10
let moreMixedTuple = ( num, "two", 3.3, squareIt )



// You can pull a function out of a tuple and apply it. Both squareIt and num
// were defined previously.
let funAndArgTuple = (squareIt, num)

// The following expression applies squareIt to num, returns 100, and
// then displays 100.
System.Console.WriteLine((fst funAndArgTuple)(snd funAndArgTuple))



// Make a list of values instead of identifiers.
let funAndArgTuple2 = ((fun n -> n * n), 10)

// The following expression applies a squaring function to 10, returns
// 100, and then displays 100.
System.Console.WriteLine((fst funAndArgTuple2)(snd funAndArgTuple2))



// ** PASS THE VALUE AS AN ARGUMENT **


// An integer is passed to squareIt. Both squareIt and num are defined in
// previous examples.
//let num = 10
//let squareIt = fun n -> n * n
System.Console.WriteLine(squareIt num)

// String.
// Function repeatString concatenates a string with itself.
let repeatString = fun s -> s + s

// A string is passed to repeatString. HelloHello is returned and displayed.
let greeting = "Hello"
System.Console.WriteLine(repeatString greeting)



// Define the function, again using lambda expression syntax.
let applyIt = fun op arg -> op arg

// Send squareIt for the function, op, and num for the argument you want to
// apply squareIt to, arg. Both squareIt and num are defined in previous
// examples. The result returned and displayed is 100.
System.Console.WriteLine(applyIt squareIt num)

// The following expression shows the concise syntax for the previous function
// definition.
let applyIt2 op arg = op arg
// The following line also displays 100.
System.Console.WriteLine(applyIt2 squareIt num)



// List integerList was defined previously:
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]

// You can send the function argument by name, if an appropriate function
// is available. The following expression uses squareIt.
let squareAll = List.map squareIt integerList

// The following line displays [1; 4; 9; 16; 25; 36; 49]
printfn "%A" squareAll

// Or you can define the action to apply to each list element inline.
// For example, no function that tests for even integers has been defined,
// so the following expression defines the appropriate function inline.
// The function returns true if n is even; otherwise it returns false.
let evenOrNot = List.map (fun n -> n % 2 = 0) integerList

// The following line displays [false; true; false; true; false; true; false]
printfn "%A" evenOrNot



// ** RETURN THE VALUE FROM A FUNCTION CALL **


// Function doubleIt is defined in a previous example.
//let doubleIt = fun n -> 2 * n
System.Console.WriteLine(doubleIt 3)
System.Console.WriteLine(squareIt 4)


// The following function call returns a string:

// str is defined in a previous section.
//let str = "F#"
let lowercase = str.ToLower()



System.Console.WriteLine((fun n -> n % 2 = 1) 15)



let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn



// integerList and stringList were defined earlier.
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
//let stringList = [ "one"; "two"; "three" ]

// The returned function is given the name checkFor7.
let checkFor7 = checkFor 7

// The result displayed when checkFor7 is applied to integerList is True.
System.Console.WriteLine(checkFor7 integerList)

// The following code repeats the process for "seven" in stringList.
let checkForSeven = checkFor "seven"

// The result displayed is False.
System.Console.WriteLine(checkForSeven stringList)



// Function compose takes two arguments. Each argument is a function
// that takes one argument of the same type. The following declaration
// uses lambda expression syntax.
let compose =
    fun op1 op2 ->
        fun n ->
            op1 (op2 n)

// To clarify what you are returning, use a nested let expression:
let compose2 =
    fun op1 op2 ->
        // Use a let expression to build the function that will be returned.
        let funToReturn = fun n ->
                            op1 (op2 n)
        // Then just return it.
        funToReturn

// Or, integrating the more concise syntax:
let compose3 op1 op2 =
    let funToReturn = fun n ->
                        op1 (op2 n)
    funToReturn



// Functions squareIt and doubleIt were defined in a previous example.
let doubleAndSquare = compose squareIt doubleIt
// The following expression doubles 3, squares 6, and returns and
// displays 36.
System.Console.WriteLine(doubleAndSquare 3)

let squareAndDouble = compose doubleIt squareIt
// The following expression squares 3, doubles 9, returns 18, and
// then displays 18.
System.Console.WriteLine(squareAndDouble 3)



let makeGame target =
    // Build a lambda expression that is the function that plays the game.
    let game = fun guess ->
                   if guess = target then
                      System.Console.WriteLine("You win!")
                   else
                      System.Console.WriteLine("Wrong. Try again.")
    // Now just return it.
    game



let playGame = makeGame 7
// Send in some guesses.
playGame 2
playGame 9
playGame 7

// Output:
// Wrong. Try again.
// Wrong. Try again.
// You win!

// The following game specifies a character instead of an integer for target.
let alphaGame = makeGame 'q'
alphaGame 'c'
alphaGame 'r'
alphaGame 'j'
alphaGame 'q'

// Output:
// Wrong. Try again.
// Wrong. Try again.
// Wrong. Try again.
// You win!



// ** CURRIED FUNCTIONS **


let compose4 op1 op2 n = op1 (op2 n)



let compose4curried =
    fun op1 ->
        fun op2 ->
            fun n -> op1 (op2 n)



// Access one layer at a time.
System.Console.WriteLine(((compose4 doubleIt) squareIt) 3)

// Access as in the original compose examples, sending arguments for
// op1 and op2, then applying the resulting function to a value.
System.Console.WriteLine((compose4 doubleIt squareIt) 3)

// Access by sending all three arguments at the same time.
System.Console.WriteLine(compose4 doubleIt squareIt 3)



let doubleAndSquare4 = compose4 squareIt doubleIt
// The following expression returns and displays 36.
System.Console.WriteLine(doubleAndSquare4 3)

let squareAndDouble4 = compose4 doubleIt squareIt
// The following expression returns and displays 18.
System.Console.WriteLine(squareAndDouble4 3)



let makeGame2 target guess =
    if guess = target then
       System.Console.WriteLine("You win!")
    else
       System.Console.WriteLine("Wrong. Try again.")

let playGame2 = makeGame2 7
playGame2 2
playGame2 9
playGame2 7

let alphaGame2 = makeGame2 'q'
alphaGame2 'c'
alphaGame2 'r'
alphaGame2 'j'
alphaGame2 'q'



// ** IDENTIFIER AND FUNCTION DEFINITION ARE INTERCHANGEABLE **


let isNegative = fun n -> n < 0

// This example uses the names of the function argument and the integer
// argument. Identifier num is defined in a previous example.
//let num = 10
System.Console.WriteLine(applyIt isNegative num)

// This example substitutes the value that num is bound to for num, and the
// value that isNegative is bound to for isNegative.
System.Console.WriteLine(applyIt (fun n -> n < 0) 10)



System.Console.WriteLine((fun op arg -> op arg) (fun n -> n < 0)  10)



// ** FUNCTIONS ARE FIRST-CLASS VALUES IN F# **

//let squareIt = fun n -> n * n


let funTuple2 = ( BMICalculator, fun n -> n * n )



let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]


//let checkFor item =
//    let functionToReturn = fun lst ->
//                           List.exists (fun a -> a = item) lst
//    functionToReturn

関連項目