共用方式為


當做優先使用值的函式 (F#)

函式程式設計語言的定義特性是將函式提高至優先使用狀態。 您應該可以用處理其他內建型別值的方式來處理函式,而且其處理工作程度相當。

優先使用狀態的一般測量包括:

  • 您是否能將識別碼繫結至此值? 也就是說,您是否能為它提供名稱?

  • 您是否能將此值儲存在清單之類的資料結構中?

  • 您是否能在函式呼叫中,將此值當做引數傳遞?

  • 您是否能傳回此值,當做函式呼叫的值?

最後兩個測量會定義稱為「高階作業」(Higher-Order Operation) 或「高階函式」(Higher-Order Function) 的項目。 高階函式會接受函式當做引數,並傳回函式當做函式呼叫的值。 這些作業支援對應函式和組合函式之類的主要函式程式設計。

為此值提供名稱

如果函式是優先使用值,您就一定能夠為它命名,就如同您可以命名整數、字串和其他內建型別一樣。 在函式程式設計中,這項作業稱為將識別碼繫結至值。 F# 會使用 let 運算式,將名稱繫結至值:let <identifier> = <value>。 下列程式碼將示範兩則範例。

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

您可以輕鬆地命名函式。 下列範例會透過將識別碼 squareIt 繫結至 lambda 運算式 fun n -> n * n,定義名為 squareIt 的函式。 函式 squareIt 具有一個參數 n,而且它會傳回該參數的平方。

let squareIt = fun n -> n * n

F# 提供了下列更簡潔的語法,以較少的輸入達到相同的結果。

let squareIt2 n = n * n

後續範例大部分會使用第一種樣式 let <function-name> = <lambda-expression> 來強調宣告函式與宣告其他型別值之間的相似處。 不過,您也可以用簡潔的語法來撰寫所有具名函式。 部分範例會以這兩種方式撰寫。

將此值儲存在資料結構中

您可以將優先使用值儲存在資料結構中。 下列程式碼會示範將值儲存在清單和 Tuple 中的範例。

// 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 )

為了確認儲存在 Tuple 中的函式名稱實際上會評估為函式,下列範例會使用 fst 和 snd 運算子,從 Tuple funAndArgTuple 中擷取第一個和第二個項目。 Tuple 中的第一個項目是 squareIt 而第二個項目是 num。 在先前的範例中,識別碼 num 會繫結至整數 10,也就是 squareIt 函式的有效引數。 第二個運算式會將 Tuple 中的第一個項目套用至 Tuple 中的第二個項目: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 和 lambda 運算式 fun n -> n * n 也可以交替使用。

// 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))

將此值當做引數傳遞

如果某個值在語言中具有優先使用狀態,您就可以將它當做引數傳遞至函式。 例如,將整數和字串當做引數傳遞就很常見。 下列程式碼會示範在 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)

如果函式具有優先使用狀態,您就一定能夠用相同的方式,將它們當做引數傳遞。 請記住,這是高階函式的第一個特性。

在下列範例中,函式 applyIt 具有兩個參數:op 和 arg。 如果您傳入需要單一參數的函式給 op,以及一個適合此函式的參數給 arg,此函式就會傳回將 op 套用至 arg 的結果。 在下列範例中,函式引數與整數引數都會使用其名稱,以相同的方式傳送。

// 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)

將函式當做引數傳送至其他函式的功能是函式程式設計語言中常見擷取作業的基礎,例如對應或篩選作業。 例如,對應作業是一種擷取函式所共用之計算的高階函式,這些函式會逐步執行清單、對每個項目進行一些作業,然後傳回結果的清單。 您可能會想要遞增整數清單中的每個項目、計算每個項目的平方,或將字串清單中的每個項目變更為大寫。 計算中容易發生錯誤的部分是逐步執行清單以及建置要傳回之結果清單的遞迴程序。 該部分是在對應函式中擷取的。 您只需要針對特定應用程式撰寫想要個別套用至每個清單項目的函式 (加入、計算平方或變更大小寫) 即可。 該函式會當做引數傳送至對應函式,就像先前範例中,squareIt 會傳送到 applyIt 一樣。

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

如需詳細資訊,請參閱 清單 (F#)

從函式呼叫傳回此值

最後,如果某個函式在語言中具有優先使用狀態,您就一定能夠傳回它,當做函式呼叫的值,就如同您傳回其他型別 (例如整數和字串) 一樣。

下列函式呼叫會傳回整數並顯示它們。

// 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)

傳回函式當做函式呼叫之值的功能是高階函式的第二個特性。 在下列範例中,checkFor 定義為函式,它會採用一個引數 item,並傳回新的函式當做它的值。 傳回的函式會採用清單當做其引數 lst,並且在 lst 中搜尋 item。 如果 item 存在,此函式就會傳回 true。 如果 item 不存在,此函式就會傳回 false。 如上一節所述,下列程式碼會使用提供的清單函式 List.exists 來搜尋清單。

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

下列程式碼會使用 checkFor 來建立新的函式,它會採用一個引數 (清單) 並且在此清單中搜尋 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# 中使用函式的優先使用狀態來宣告函式 compose,以便傳回兩個函式引數的組合。

// Function compose takes two arguments. Each argument is a function 
// that takes one argument of the same type. The following declaration
// uses lambda expresson 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
注意事項注意事項

如需更短的版本,請參閱下一節<局部調用函式>。

下列程式碼會將兩個函式當做引數傳送至 compose,而這兩個函式都會採用相同型別的單一引數。 傳回值就是兩個函式引數之組合的新函式。

// 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# 提供了兩個組合函式的運算子:<< 和 >>。 例如,let squareAndDouble2 = doubleIt << squareIt 就相當於上述範例的 let squareAndDouble = compose doubleIt squareIt。

下列傳回函式當做函式呼叫之值的範例會建立簡單的猜謎遊戲。 若要建立遊戲,請呼叫 makeGame 並將您想讓某人猜測的值傳入 target。 函式 makeGame 的傳回值就是採用一個引數 (猜謎) 並回報猜測是否正確的函式。

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 會繫結至傳回的 lambda 運算式。 因此,playGame 就是採用一個引數做為 guess 值的函式。

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# 函式宣告中隱含的「局部調用」(Currying),就能以更簡潔的方式撰寫上一節中的大部分範例。 局部調用是將具有多個參數的函式轉換成一系列內嵌函式的程序,而且每個函式都具有單一參數。 在 F# 中,具有多個參數的函式原本就會進行局部調用。 例如,上一節的 compose 可以撰寫成下列簡潔樣式 (具有三個參數)。

let compose4 op1 op2 n = op1 (op2 n)

不過,其結果是具有單一參數的函式,這個函式會傳回具有單一參數的函式,而此函式又接著傳回另一個具有單一參數的函式,如 compose4curried 中所示。

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

您可以用許多方式存取這個函式。 下列每則範例都會傳回並顯示 18。 您可以在任何範例中,將 compose4 取代成 compose4curried。

// 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)
注意事項注意事項

您可以將參數封入 Tuple 中,藉以限制局部調用。 如需詳細資訊,請參閱參數和引數 (F#)中的<參數模式>。

下列範例會使用隱含局部調用來撰寫較短版本的 makeGame。 雖然在這種格式中,makeGame 如何建構並傳回 game 函式的詳細資料較不明確,不過您可以使用結果相同的原始測試案例來進行確認。

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'

如需部分調用的詳細資訊,請參閱函式 (F#)中的<部分套用引數>。

識別碼和函式定義可互換

在先前的範例中,變數名稱 num 會評估為整數 10,因此只要 num 有效,10 也會有效。 函式識別碼及其值也一樣:只要可以使用函式的名稱,就可以使用它所繫結的 lambda 運算式。

下列範例會定義名為 isNegative 的 Boolean 函式,然後交替使用函式的名稱和函式的定義。 後續三個範例都會傳回並顯示 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) 

若要更進一步,請用 applyIt 所繫結的值來取代 applyIt。

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

函式是 F# 中的優先使用值

上述各節中的範例示範了 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# 的詳細資訊,請參閱 Visual F# 2010 的新功能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 expresson 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

請參閱

參考

Tuple (F#)

函式 (F#)

let 繫結 (F#)

Lambda 運算式:fun 關鍵字 (F#)

其他資源

清單 (F#)