Share via


Functies gebruiken in F#

Een eenvoudige functiedefinitie lijkt op het volgende:

let f x = x + 1

In het vorige voorbeeld is fde naam van de functie , het argument xis , wat type heeft int, de hoofdtekst van de functie is x + 1en de retourwaarde is van het type int.

Een definitiekend kenmerk van F# is dat functies de eersteklas status hebben. U kunt met een functie doen wat u kunt doen met waarden van de andere ingebouwde typen, met een vergelijkbare mate van inspanning.

  • U kunt functiewaardennamen geven.

  • U kunt functies opslaan in gegevensstructuren, zoals in een lijst.

  • U kunt een functie doorgeven als argument in een functieaanroep.

  • U kunt een functie retourneren vanuit een functie-aanroep.

Geef de waarde een naam

Als een functie een eersteklas waarde is, moet u deze een naam kunnen geven, net zoals u gehele getallen, tekenreeksen en andere ingebouwde typen kunt noemen. Dit wordt in functionele programmeerliteratuur aangeduid als binding van een id aan een waarde. F# maakt gebruik van let bindingen om namen te binden aan waarden: let <identifier> = <value>. In de volgende code ziet u twee voorbeelden.

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

U kunt een functie net zo eenvoudig een naam opgeven. In het volgende voorbeeld wordt een functie gedefinieerd die wordt benoemd squareIt door de id squareIt te binden aan de lambda-expressiefun n -> n * n. De functie squareIt heeft één parameter en nretourneert het kwadraat van die parameter.

let squareIt = fun n -> n * n

F# biedt de volgende beknoptere syntaxis om hetzelfde resultaat te bereiken met minder typen.

let squareIt2 n = n * n

De volgende voorbeelden gebruiken meestal de eerste stijl let <function-name> = <lambda-expression>, om de overeenkomsten tussen de declaratie van functies en de declaratie van andere typen waarden te benadrukken. Alle benoemde functies kunnen echter ook worden geschreven met de beknopte syntaxis. Sommige voorbeelden worden op beide manieren geschreven.

De waarde opslaan in een gegevensstructuur

Een eersteklas waarde kan worden opgeslagen in een gegevensstructuur. De volgende code toont voorbeelden waarin waarden worden opgeslagen in lijsten en tuples.

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

Om te controleren of een functienaam die in een tuple is opgeslagen, in feite een functie evalueert, worden in het volgende voorbeeld de fst en snd operators gebruikt om de eerste en tweede elementen uit de tuple funAndArgTuplete extraheren. Het eerste element in de tuple is squareIt en het tweede element is num. De id num is gebonden in een vorig voorbeeld aan geheel getal 10, een geldig argument voor de squareIt functie. De tweede expressie past het eerste element in de tuple toe op het tweede element in de 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))

Op dezelfde manier kunnen id's num en gehele getallen 10 door elkaar worden gebruikt, zodat de id squareIt en lambda-expressie fun n -> n * nkunnen worden gebruikt.

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

De waarde doorgeven als argument

Als een waarde een eersteklas status in een taal heeft, kunt u deze als argument doorgeven aan een functie. Het is bijvoorbeeld gebruikelijk om gehele getallen en tekenreeksen als argumenten door te geven. De volgende code toont gehele getallen en tekenreeksen die als argumenten worden doorgegeven in 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)

Als functies een eersteklas status hebben, moet u deze op dezelfde manier als argumenten kunnen doorgeven. Houd er rekening mee dat dit het eerste kenmerk is van functies in hogere volgorde.

In het volgende voorbeeld heeft de functie applyIt twee parameters en op arg. Als u een functie verzendt met één parameter voor op en een geschikt argument voor de functie arg, retourneert de functie het resultaat van het toepassen op op arg. In het volgende voorbeeld worden zowel het functieargument als het argument geheel getal op dezelfde manier verzonden met behulp van hun namen.

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

De mogelijkheid om een functie als argument naar een andere functie te verzenden, komt ten grondslag aan algemene abstracties in functionele programmeertalen, zoals kaart- of filterbewerkingen. Een kaartbewerking is bijvoorbeeld een functie met een hogere volgorde waarmee de berekening wordt vastgelegd die wordt gedeeld door functies die een lijst doorlopen, iets doen aan elk element en vervolgens een lijst met de resultaten retourneren. Mogelijk wilt u elk element in een lijst met gehele getallen verhogen of elk element kwadrateren of elk element in een lijst met tekenreeksen wijzigen in hoofdletters. Het foutgevoelige deel van de berekening is het recursieve proces dat de lijst doorloopt en een lijst maakt met de resultaten die moeten worden geretourneerd. Dat deel wordt vastgelegd in de toewijzingsfunctie. Het enige wat u hoeft te schrijven voor een bepaalde toepassing is de functie die u afzonderlijk wilt toepassen op elk lijstelement (toevoegen, kwadratuur, veranderende hoofdletters). Deze functie wordt als argument naar de toewijzingsfunctie verzonden, net zoals squareIt in het vorige voorbeeld wordt verzonden applyIt .

F# biedt kaartmethoden voor de meeste verzamelingstypen, waaronder lijsten, matrices en reeksen. In de volgende voorbeelden worden lijsten gebruikt. De syntaxis is 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

Zie Lijsten voor meer informatie.

De waarde van een functieoproep retourneren

Als een functie een eersteklas status in een taal heeft, moet u deze kunnen retourneren als de waarde van een functie-aanroep, net zoals u andere typen retourneert, zoals gehele getallen en tekenreeksen.

Met de volgende functie aanroepen worden gehele getallen geretourneerd en weergegeven.

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

Met de volgende functieoproep wordt een tekenreeks geretourneerd.

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

Met de volgende functieaanroep, gedeclareerd inline, wordt een Booleaanse waarde geretourneerd. De weergegeven waarde is True.

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

De mogelijkheid om een functie als de waarde van een functie-aanroep te retourneren, is het tweede kenmerk van functies in een hogere volgorde. In het volgende voorbeeld checkFor wordt gedefinieerd dat het een functie is die één argument itemgebruikt en een nieuwe functie retourneert als waarde. De geretourneerde functie gebruikt een lijst als argument lsten zoekt naar item in lst. Als item deze aanwezig is, retourneert truede functie . Als item deze niet aanwezig is, retourneert falsede functie . Net als in de vorige sectie maakt de volgende code gebruik van een opgegeven lijstfunctie, List.exists, om de lijst te doorzoeken.

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

De volgende code gebruikt checkFor om een nieuwe functie te maken die één argument, een lijst en zoekt naar 7 in de lijst.

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

In het volgende voorbeeld wordt de eersteklas status van functies in F# gebruikt om een functie te declareren, composewaarmee een samenstelling van twee functieargumenten wordt geretourneerd.

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

Notitie

Zie de volgende sectie, 'Curried Functions', voor een nog kortere versie.

Met de volgende code worden twee functies als argumenten verzonden, composewaarvan beide één argument van hetzelfde type hebben. De retourwaarde is een nieuwe functie die een samenstelling is van de twee functieargumenten.

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

Notitie

F# biedt twee operators en << >>, die functies opstellen. Is bijvoorbeeld let squareAndDouble2 = doubleIt << squareIt gelijk aan let squareAndDouble = compose doubleIt squareIt in het vorige voorbeeld.

In het volgende voorbeeld van het retourneren van een functie als waarde van een functie-aanroep wordt een eenvoudig radend spel gemaakt. Als u een game wilt maken, belt makeGame u met de waarde waarvoor iemand moet raden target. De retourwaarde van de functie makeGame is een functie die één argument (de schatting) gebruikt en rapporteert of de schatting juist is.

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

Met de volgende code aanroepen makeGame, wordt de waarde 7 voor targetverzonden. De id playGame is gebonden aan de geretourneerde lambda-expressie. playGame Daarom is een functie die als één argument een waarde voor 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!

Curriede functies

Veel van de voorbeelden in de vorige sectie kunnen beknopter worden geschreven door gebruik te maken van de impliciete kerrie in F#-functiedeclaraties. Currying is een proces waarmee een functie met meer dan één parameter wordt getransformeerd in een reeks ingesloten functies, die elk één parameter hebben. In F# worden functies met meer dan één parameter inherent gecureerd. Uit de vorige sectie kan bijvoorbeeld compose worden geschreven zoals wordt weergegeven in de volgende beknopte stijl, met drie parameters.

let compose4 op1 op2 n = op1 (op2 n)

Het resultaat is echter een functie van een parameter die een functie retourneert van een parameter die op zijn beurt een andere functie van een parameter retourneert, zoals wordt weergegeven in compose4curried.

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

U kunt deze functie op verschillende manieren openen. Elk van de volgende voorbeelden retourneert en geeft 18 weer. U kunt vervangen door compose4 compose4curried een van de voorbeelden.

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

Als u wilt controleren of de functie nog steeds werkt zoals voorheen, probeert u de oorspronkelijke testcases opnieuw.

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)

Notitie

U kunt kerrie beperken door parameters in tuples in te sluiten. Zie Parameterpatronen in Parameters en Argumenten voor meer informatie.

In het volgende voorbeeld wordt impliciete kerrie gebruikt om een kortere versie van makeGame. De details van hoe makeGame de game functie wordt samengesteld en geretourneerd, zijn minder expliciet in deze indeling, maar u kunt controleren met behulp van de oorspronkelijke testcases dat het resultaat hetzelfde is.

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'

Zie 'Gedeeltelijke toepassing van argumenten' in Functies voor meer informatie over kerrie.

Id en functiedefinitie zijn uitwisselbaar

De naam num van de variabele in de vorige voorbeelden resulteert in het gehele getal 10 en het is geen verrassing dat num waar geldig is, 10 ook geldig is. Hetzelfde geldt voor functie-id's en hun waarden: overal waar de naam van de functie kan worden gebruikt, kan de lambda-expressie waaraan deze is gebonden, worden gebruikt.

In het volgende voorbeeld wordt een Boolean functie gedefinieerd die wordt aangeroepen isNegativeen wordt vervolgens de naam van de functie en de definitie van de functie door elkaar gebruikt. De volgende drie voorbeelden retourneren en weergeven 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)

Als u het nog een stap verder wilt doen, vervangt u de waarde die applyIt is gebonden aan applyIt.

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

Functies zijn eersteklas waarden in F#

De voorbeelden in de vorige secties laten zien dat functies in F# voldoen aan de criteria voor het zijn van eersteklas waarden in F#:

  • U kunt een id binden aan een functiedefinitie.
let squareIt = fun n -> n * n
  • U kunt een functie opslaan in een gegevensstructuur.
let funTuple2 = ( BMICalculator, fun n -> n * n )
  • U kunt een functie doorgeven als argument.
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
  • U kunt een functie retourneren als de waarde van een functie-aanroep.
let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

Zie de F#-taalreferentie voor meer informatie over F#.

Opmerking

Beschrijving

De volgende code bevat alle voorbeelden in dit onderwerp.

Code

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

Zie ook