Header menu logo Teaching

BinderScriptNotebook

Working with Tuples and Records.

Developed with Davide Costa

This set of exercises covers creating and manipulating tuples, records, and anonymous records. Before you start it is a good idea to review the relevant sections of the F# language reference ( tuples, records, and anonymous records ) and F# for fun and profit ( tuples and records) before you start.

Import the Football Players Data from the Csv File

#r "nuget: FSharp.Data, 5.0.2"
open FSharp.Data

In order to import the data correctly we need to create the sample, define the type from the sample and then load the csv file. We'll use FSharp.Data CsvProvider.

Load the Csv file.

We define the type from the csv sample file.

let [<Literal>] CsvPath = __SOURCE_DIRECTORY__ + "/FootballPlayers.csv"
type FootballPlayersCsv = CsvProvider<CsvPath>

This will load the sample csv file.

let playerStatsTable = 
    FootballPlayersCsv.GetSample().Rows
    |> Seq.toList

Let's see the first 5 rows from the loaded Csv data, stored in playerStatsTable. Again, we do this by using the List List.truncate property.

playerStatsTable
|> List.truncate 5
val it: CsvProvider<...>.Row list =
  [("Robert Lewandowski", "pl POL", "FW", "Bayern Munich", "deBundesliga", 32,
    34, 35);
   ("Kylian Mbappé", "fr FRA", "FW", "Paris S-G", "frLigue 1", 22, 35, 28);
   ("Karim Benzema", "fr FRA", "FW", "Real Madrid", "esLa Liga", 33, 32, 27);
   ("Ciro Immobile", "it ITA", "FW", "Lazio", "itSerie A", 31, 31, 27);
   ("Wissam Ben Yedder", "fr FRA", "FW", "Monaco", "frLigue 1", 30, 37, 25)]

EXERCISES - PART 1

Transforming collections

Creating tuples

Example: Transform each element of the playerStatsTable List into a tuple with the player and nation ( Player, Nation)

playerStatsTable
|> List.map(fun x -> x.Player, x.Nation)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * string) list =
  [("Robert Lewandowski", "pl POL"); ("Kylian Mbappé", "fr FRA");
   ("Karim Benzema", "fr FRA"); ("Ciro Immobile", "it ITA");
   ("Wissam Ben Yedder", "fr FRA")]

answer

playerStatsTable
|> List.map(fun x -> x.Player, x.Team)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * string) list =
  [("Robert Lewandowski", "Bayern Munich"); ("Kylian Mbappé", "Paris S-G");
   ("Karim Benzema", "Real Madrid"); ("Ciro Immobile", "Lazio");
   ("Wissam Ben Yedder", "Monaco")]

answer

playerStatsTable
|> List.map(fun x -> x.Player, x.League)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * string) list =
  [("Robert Lewandowski", "deBundesliga"); ("Kylian Mbappé", "frLigue 1");
   ("Karim Benzema", "esLa Liga"); ("Ciro Immobile", "itSerie A");
   ("Wissam Ben Yedder", "frLigue 1")]

answer

playerStatsTable
|> List.map(fun x -> x.Player, x.Age)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * int) list =
  [("Robert Lewandowski", 32); ("Kylian Mbappé", 22); ("Karim Benzema", 33);
   ("Ciro Immobile", 31); ("Wissam Ben Yedder", 30)]

answer

playerStatsTable
|> List.map(fun x -> x.Player, x.MatchesPlayed)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * int) list =
  [("Robert Lewandowski", 34); ("Kylian Mbappé", 35); ("Karim Benzema", 32);
   ("Ciro Immobile", 31); ("Wissam Ben Yedder", 37)]

answer

playerStatsTable
|> List.map(fun x -> x.Player, x.GoalsScored)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * int) list =
  [("Robert Lewandowski", 35); ("Kylian Mbappé", 28); ("Karim Benzema", 27);
   ("Ciro Immobile", 27); ("Wissam Ben Yedder", 25)]

Creating records

Example: Define a record named PlayerAndNation with a field named Player that is a string and Nation that is a string. Then transform each element of the playerStatsTable List into a PlayerAndNation record.

type PlayerAndNation =
    { Player : string 
      Nation : string }

The above code creates a record type called PlayerAndNation. This record contains two fields: Player of string type and Nation of string type. Remember, if the types from the csv file are different an error will occur when creating an instance of the record.

Common types:

Check basic types documentation to learn about F# basic types.

Now by having the record type created we can map the playerStatsTable rows to the record PlayerAndNation.

playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player
      Nation = x.Nation })
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: PlayerAndNation list =
  [{ Player = "Robert Lewandowski"
     Nation = "pl POL" }; { Player = "Kylian Mbappé"
                            Nation = "fr FRA" }; { Player = "Karim Benzema"
                                                   Nation = "fr FRA" };
   { Player = "Ciro Immobile"
     Nation = "it ITA" }; { Player = "Wissam Ben Yedder"
                            Nation = "fr FRA" }]

Note that you choose the name of the fields in the record. Instead of Player it could be anything. The following code block for example would have also worked, but the field name for the player is PlayerName instead of Player and Nationality instead of Nation:

type PlayerAndNation2 =
    { PlayerName : string 
      Nationality : string }

playerStatsTable
|> List.map(fun x -> 
    { PlayerName = x.Player
      Nationality = x.Nation })

answer

type PlayerAndTeam =
    { Player : string
      Team : string }
   
playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player 
      Team = x.Team })
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndTeam =
  {
    Player: string
    Team: string
  }
val it: PlayerAndTeam list =
  [{ Player = "Robert Lewandowski"
     Team = "Bayern Munich" }; { Player = "Kylian Mbappé"
                                 Team = "Paris S-G" };
   { Player = "Karim Benzema"
     Team = "Real Madrid" }; { Player = "Ciro Immobile"
                               Team = "Lazio" };
   { Player = "Wissam Ben Yedder"
     Team = "Monaco" }]

answer

type PlayerAndLeague =
    { Player : string
      League : string }

playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player
      League = x.League })
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndLeague =
  {
    Player: string
    League: string
  }
val it: PlayerAndLeague list =
  [{ Player = "Robert Lewandowski"
     League = "deBundesliga" }; { Player = "Kylian Mbappé"
                                  League = "frLigue 1" };
   { Player = "Karim Benzema"
     League = "esLa Liga" }; { Player = "Ciro Immobile"
                               League = "itSerie A" };
   { Player = "Wissam Ben Yedder"
     League = "frLigue 1" }]

answer

type PlayerAndAge =
    { Player : string
      Age : int }

playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player
      Age =  x.Age })
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndAge =
  {
    Player: string
    Age: int
  }
val it: PlayerAndAge list =
  [{ Player = "Robert Lewandowski"
     Age = 32 }; { Player = "Kylian Mbappé"
                   Age = 22 }; { Player = "Karim Benzema"
                                 Age = 33 }; { Player = "Ciro Immobile"
                                               Age = 31 };
   { Player = "Wissam Ben Yedder"
     Age = 30 }]

answer

type PlayerAndMatchesPlayed =
    { Player : string
      MatchesPlayed : int }

playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player 
      MatchesPlayed = x.MatchesPlayed})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndMatchesPlayed =
  {
    Player: string
    MatchesPlayed: int
  }
val it: PlayerAndMatchesPlayed list =
  [{ Player = "Robert Lewandowski"
     MatchesPlayed = 34 }; { Player = "Kylian Mbappé"
                             MatchesPlayed = 35 }; { Player = "Karim Benzema"
                                                     MatchesPlayed = 32 };
   { Player = "Ciro Immobile"
     MatchesPlayed = 31 }; { Player = "Wissam Ben Yedder"
                             MatchesPlayed = 37 }]

answer

type PlayerAndGoalsScored = 
    { Player : string
      GoalsScored : int }

playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player 
      GoalsScored = x.GoalsScored })
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndGoalsScored =
  {
    Player: string
    GoalsScored: int
  }
val it: PlayerAndGoalsScored list =
  [{ Player = "Robert Lewandowski"
     GoalsScored = 35 }; { Player = "Kylian Mbappé"
                           GoalsScored = 28 }; { Player = "Karim Benzema"
                                                 GoalsScored = 27 };
   { Player = "Ciro Immobile"
     GoalsScored = 27 }; { Player = "Wissam Ben Yedder"
                           GoalsScored = 25 }]

Creating anonymous records

Example: Transform each element of the playerStatsTable List into an anonymous record with a Player field that is a string and a Nation field that is a string.

With Anonymous records we don't need to define the record type beforehand and we don't need to specify the type of each field.

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player
       Nation = x.Nation |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| Nation: string; Player: string |} list =
  [{ Nation = "pl POL"
     Player = "Robert Lewandowski" }; { Nation = "fr FRA"
                                        Player = "Kylian Mbappé" };
   { Nation = "fr FRA"
     Player = "Karim Benzema" }; { Nation = "it ITA"
                                   Player = "Ciro Immobile" };
   { Nation = "fr FRA"
     Player = "Wissam Ben Yedder" }]

answer

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player 
       Team = x.Team |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| Player: string; Team: string |} list =
  [{ Player = "Robert Lewandowski"
     Team = "Bayern Munich" }; { Player = "Kylian Mbappé"
                                 Team = "Paris S-G" };
   { Player = "Karim Benzema"
     Team = "Real Madrid" }; { Player = "Ciro Immobile"
                               Team = "Lazio" };
   { Player = "Wissam Ben Yedder"
     Team = "Monaco" }]

answer

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player
       League = x.League |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| League: string; Player: string |} list =
  [{ League = "deBundesliga"
     Player = "Robert Lewandowski" }; { League = "frLigue 1"
                                        Player = "Kylian Mbappé" };
   { League = "esLa Liga"
     Player = "Karim Benzema" }; { League = "itSerie A"
                                   Player = "Ciro Immobile" };
   { League = "frLigue 1"
     Player = "Wissam Ben Yedder" }]

answer

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player
       Age =  x.Age |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| Age: int; Player: string |} list =
  [{ Age = 32
     Player = "Robert Lewandowski" }; { Age = 22
                                        Player = "Kylian Mbappé" };
   { Age = 33
     Player = "Karim Benzema" }; { Age = 31
                                   Player = "Ciro Immobile" };
   { Age = 30
     Player = "Wissam Ben Yedder" }]

answer

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player 
       MatchesPlayed = x.MatchesPlayed |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| MatchesPlayed: int; Player: string |} list =
  [{ MatchesPlayed = 34
     Player = "Robert Lewandowski" }; { MatchesPlayed = 35
                                        Player = "Kylian Mbappé" };
   { MatchesPlayed = 32
     Player = "Karim Benzema" }; { MatchesPlayed = 31
                                   Player = "Ciro Immobile" };
   { MatchesPlayed = 37
     Player = "Wissam Ben Yedder" }]

answer

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player 
       GoalsScored = x.GoalsScored |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| GoalsScored: int; Player: string |} list =
  [{ GoalsScored = 35
     Player = "Robert Lewandowski" }; { GoalsScored = 28
                                        Player = "Kylian Mbappé" };
   { GoalsScored = 27
     Player = "Karim Benzema" }; { GoalsScored = 27
                                   Player = "Ciro Immobile" };
   { GoalsScored = 25
     Player = "Wissam Ben Yedder" }]

Simple transformations

Now that you are used to work with List.map to organize the data into tuples, records and anonymous records. Let's try to do it while applying some simple transformations as sum, multiplication, type transformations and so on.

Transformations using tuples

Example: map the playerStatsTable to a tuple of player and age, but add 1 to age. ( Player, Age + 1)

playerStatsTable
|> List.map(fun x -> x.Age + 1)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: int list = [33; 23; 34; 32; 31]

When to use integers or floats/decimals:

  1. Use integers if the results of the calculations should be integers (1, 2, 3, 4, ...).
  2. Use floats or decimals if the results of the calculations may be floats or decimals (1.1, 2.1324, ...).

answer

playerStatsTable
|> List.map(fun  x-> x.Player, x.GoalsScored * 10)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * int) list =
  [("Robert Lewandowski", 350); ("Kylian Mbappé", 280); ("Karim Benzema", 270);
   ("Ciro Immobile", 270); ("Wissam Ben Yedder", 250)]

answer

playerStatsTable
|> List.map(fun x -> x.Player, float x.GoalsScored / 2.0)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * int) list =
  [("Robert Lewandowski", 17); ("Kylian Mbappé", 14); ("Karim Benzema", 13);
   ("Ciro Immobile", 13); ("Wissam Ben Yedder", 12)]

In this case, look how dividing using integers rounds the results to the nearest integers. If the results are decimals you might prefer to get exact results. For that you can use floats or decimals types. In order to convert a variable to float you have to use the syntax: float variable.

Example: map the playerStatsTable to a tuple of player and age, but convert age to float. ( Player, float Age)

playerStatsTable
|> List.map(fun x -> x.Player, float x.Age) 
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * float) list =
  [("Robert Lewandowski", 32.0); ("Kylian Mbappé", 22.0);
   ("Karim Benzema", 33.0); ("Ciro Immobile", 31.0);
   ("Wissam Ben Yedder", 30.0)]

answer

playerStatsTable
|> List.map(fun x -> x.Player, float x.GoalsScored) 
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * float) list =
  [("Robert Lewandowski", 35.0); ("Kylian Mbappé", 28.0);
   ("Karim Benzema", 27.0); ("Ciro Immobile", 27.0);
   ("Wissam Ben Yedder", 25.0)]

answer

playerStatsTable
|> List.map(fun x -> x.Player, float x.GoalsScored / 2.0)
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: (string * int) list =
  [("Robert Lewandowski", 17); ("Kylian Mbappé", 14); ("Karim Benzema", 13);
   ("Ciro Immobile", 13); ("Wissam Ben Yedder", 12)]

Transformations using records

Example: map the playerStatsTable to a record of player and age, but add 1 to age. ( Player, Age + 1)

type PlayerAndAgePlus1Int =
    { Player : string
      AgePlus1Int : int }

playerStatsTable
|> List.map(fun x ->
    { Player = x.Player 
      AgePlus1Int = x.Age + 1})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndAgePlus1Int =
  {
    Player: string
    AgePlus1Int: int
  }
val it: PlayerAndAgePlus1Int list =
  [{ Player = "Robert Lewandowski"
     AgePlus1Int = 33 }; { Player = "Kylian Mbappé"
                           AgePlus1Int = 23 }; { Player = "Karim Benzema"
                                                 AgePlus1Int = 34 };
   { Player = "Ciro Immobile"
     AgePlus1Int = 32 }; { Player = "Wissam Ben Yedder"
                           AgePlus1Int = 31 }]

answer

type PlayerAndGls = 
    { Player : string 
      GoalsScored : int}

playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player 
      GoalsScored = x.GoalsScored * 10 })
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndGls =
  {
    Player: string
    GoalsScored: int
  }
val it: PlayerAndGls list =
  [{ Player = "Robert Lewandowski"
     GoalsScored = 350 }; { Player = "Kylian Mbappé"
                            GoalsScored = 280 }; { Player = "Karim Benzema"
                                                   GoalsScored = 270 };
   { Player = "Ciro Immobile"
     GoalsScored = 270 }; { Player = "Wissam Ben Yedder"
                            GoalsScored = 250 }]

answer

type PlayerAndGlsFloat = 
    { Player : string 
      GoalsScoredFloat : float}

playerStatsTable
|> List.map(fun x -> 
    { Player = x.Player 
      GoalsScoredFloat = (float x.GoalsScored) / 2.0 })
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type PlayerAndGlsFloat =
  {
    Player: string
    GoalsScoredFloat: float
  }
val it: PlayerAndGlsFloat list =
  [{ Player = "Robert Lewandowski"
     GoalsScoredFloat = 17.5 }; { Player = "Kylian Mbappé"
                                  GoalsScoredFloat = 14.0 };
   { Player = "Karim Benzema"
     GoalsScoredFloat = 13.5 }; { Player = "Ciro Immobile"
                                  GoalsScoredFloat = 13.5 };
   { Player = "Wissam Ben Yedder"
     GoalsScoredFloat = 12.5 }]

Transformations using anonymous records

Example: map the playerStatsTable to an anonymoys record of player and age, but add 1 to age. ( Player, Age + 1)

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player
       AgePlus1 = x.Age + 1 |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| AgePlus1: int; Player: string |} list =
  [{ AgePlus1 = 33
     Player = "Robert Lewandowski" }; { AgePlus1 = 23
                                        Player = "Kylian Mbappé" };
   { AgePlus1 = 34
     Player = "Karim Benzema" }; { AgePlus1 = 32
                                   Player = "Ciro Immobile" };
   { AgePlus1 = 31
     Player = "Wissam Ben Yedder" }]
// or 

playerStatsTable
|> List.map(fun x ->
    {| Player = x.Player 
       AgePlus1Float = (float x.Age) + 1.0 |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| AgePlus1Float: float; Player: string |} list =
  [{ AgePlus1Float = 33.0
     Player = "Robert Lewandowski" }; { AgePlus1Float = 23.0
                                        Player = "Kylian Mbappé" };
   { AgePlus1Float = 34.0
     Player = "Karim Benzema" }; { AgePlus1Float = 32.0
                                   Player = "Ciro Immobile" };
   { AgePlus1Float = 31.0
     Player = "Wissam Ben Yedder" }]

answer

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player 
       GoalsScoredFloat = x.GoalsScored * 10 |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.

// or 

playerStatsTable
|> List.map(fun x ->
    {| Player = x.Player 
       AgePlus1Float = (float x.GoalsScored) * 10.0 |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| AgePlus1Float: float; Player: string |} list =
  [{ AgePlus1Float = 350.0
     Player = "Robert Lewandowski" }; { AgePlus1Float = 280.0
                                        Player = "Kylian Mbappé" };
   { AgePlus1Float = 270.0
     Player = "Karim Benzema" }; { AgePlus1Float = 270.0
                                   Player = "Ciro Immobile" };
   { AgePlus1Float = 250.0
     Player = "Wissam Ben Yedder" }]

answer

playerStatsTable
|> List.map(fun x -> 
    {| Player = x.Player 
       GoalsScoredFloat = (float x.GoalsScored) / 2.0 |})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
val it: {| GoalsScoredFloat: float; Player: string |} list =
  [{ GoalsScoredFloat = 17.5
     Player = "Robert Lewandowski" }; { GoalsScoredFloat = 14.0
                                        Player = "Kylian Mbappé" };
   { GoalsScoredFloat = 13.5
     Player = "Karim Benzema" }; { GoalsScoredFloat = 13.5
                                   Player = "Ciro Immobile" };
   { GoalsScoredFloat = 12.5
     Player = "Wissam Ben Yedder" }]

Creating and transforming TeamRecord

Now that you are used to work with records and perform simple Transformations, map playerStatsTable to a record type that includes:

Hint: Create a new type.

answer

type TeamRecord = 
    { Player : string
      Nation : string
      League : string
      AgeNextYear : int
      HalfGoalsScored : float }

playerStatsTable
|> List.map(fun x ->
    { Player = x.Player
      Nation = x.Nation
      League = x.League
      AgeNextYear = x.Age + 1
      HalfGoalsScored = float x.GoalsScored / 2.0})
|> List.truncate 5 //just to observe the first 5 rows, not a part of the exercise.
type TeamRecord =
  {
    Player: string
    Nation: string
    League: string
    AgeNextYear: int
    HalfGoalsScored: float
  }
val it: TeamRecord list =
  [{ Player = "Robert Lewandowski"
     Nation = "pl POL"
     League = "deBundesliga"
     AgeNextYear = 33
     HalfGoalsScored = 17.5 }; { Player = "Kylian Mbappé"
                                 Nation = "fr FRA"
                                 League = "frLigue 1"
                                 AgeNextYear = 23
                                 HalfGoalsScored = 14.0 };
   { Player = "Karim Benzema"
     Nation = "fr FRA"
     League = "esLa Liga"
     AgeNextYear = 34
     HalfGoalsScored = 13.5 }; { Player = "Ciro Immobile"
                                 Nation = "it ITA"
                                 League = "itSerie A"
                                 AgeNextYear = 32
                                 HalfGoalsScored = 13.5 };
   { Player = "Wissam Ben Yedder"
     Nation = "fr FRA"
     League = "frLigue 1"
     AgeNextYear = 31
     HalfGoalsScored = 12.5 }]

val makeNumberedHeading: htmlTag: string -> text: string -> string
val htmlTag: string
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
val text: string
val name: string
System.String.Replace(oldValue: string, newValue: string) : string
System.String.Replace(oldChar: char, newChar: char) : string
System.String.Replace(oldValue: string, newValue: string, comparisonType: System.StringComparison) : string
System.String.Replace(oldValue: string, newValue: string, ignoreCase: bool, culture: System.Globalization.CultureInfo) : string
val snippet: string
val sprintf: format: Printf.StringFormat<'T> -> 'T
val H2: (string -> string)
val H3: (string -> string)
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
Multiple items
type LiteralAttribute = inherit Attribute new: unit -> LiteralAttribute

--------------------
new: unit -> LiteralAttribute
[<Literal>] val CsvPath: string = "D:\a\Teaching\Teaching\docs/FootballPlayers.csv"
type FootballPlayersCsv = CsvProvider<...>
type CsvProvider
<summary>Typed representation of a CSV file.</summary> <param name='Sample'>Location of a CSV sample file or a string containing a sample CSV document.</param> <param name='Separators'>Column delimiter(s). Defaults to <c>,</c>.</param> <param name='InferRows'>Number of rows to use for inference. Defaults to <c>1000</c>. If this is zero, all rows are used.</param> <param name='Schema'>Optional column types, in a comma separated list. Valid types are <c>int</c>, <c>int64</c>, <c>bool</c>, <c>float</c>, <c>decimal</c>, <c>date</c>, <c>datetimeoffset</c>, <c>timespan</c>, <c>guid</c>, <c>string</c>, <c>int?</c>, <c>int64?</c>, <c>bool?</c>, <c>float?</c>, <c>decimal?</c>, <c>date?</c>, <c>datetimeoffset?</c>, <c>timespan?</c>, <c>guid?</c>, <c>int option</c>, <c>int64 option</c>, <c>bool option</c>, <c>float option</c>, <c>decimal option</c>, <c>date option</c>, <c>datetimeoffset option</c>, <c>timespan option</c>, <c>guid option</c> and <c>string option</c>. You can also specify a unit and the name of the column like this: <c>Name (type&lt;unit&gt;)</c>, or you can override only the name. If you don't want to specify all the columns, you can reference the columns by name like this: <c>ColumnName=type</c>.</param> <param name='HasHeaders'>Whether the sample contains the names of the columns as its first line.</param> <param name='IgnoreErrors'>Whether to ignore rows that have the wrong number of columns or which can't be parsed using the inferred or specified schema. Otherwise an exception is thrown when these rows are encountered.</param> <param name='SkipRows'>Skips the first n rows of the CSV file.</param> <param name='AssumeMissingValues'>When set to true, the type provider will assume all columns can have missing values, even if in the provided sample all values are present. Defaults to false.</param> <param name='PreferOptionals'>When set to true, inference will prefer to use the option type instead of nullable types, <c>double.NaN</c> or <c>""</c> for missing values. Defaults to false.</param> <param name='Quote'>The quotation mark (for surrounding values containing the delimiter). Defaults to <c>"</c>.</param> <param name='MissingValues'>The set of strings recognized as missing values specified as a comma-separated string (e.g., "NA,N/A"). Defaults to <c>NaN,NA,N/A,#N/A,:,-,TBA,TBD</c>.</param> <param name='CacheRows'>Whether the rows should be caches so they can be iterated multiple times. Defaults to true. Disable for large datasets.</param> <param name='Culture'>The culture used for parsing numbers and dates. Defaults to the invariant culture.</param> <param name='Encoding'>The encoding used to read the sample. You can specify either the character set name or the codepage number. Defaults to UTF8 for files, and to ISO-8859-1 the for HTTP requests, unless <c>charset</c> is specified in the <c>Content-Type</c> response header.</param> <param name='ResolutionFolder'>A directory that is used when resolving relative file references (at design time and in hosted execution).</param> <param name='EmbeddedResource'>When specified, the type provider first attempts to load the sample from the specified resource (e.g. 'MyCompany.MyAssembly, resource_name.csv'). This is useful when exposing types generated by the type provider.</param>
val playerStatsTable: CsvProvider<...>.Row list
CsvProvider<...>.GetSample() : CsvProvider<...>
module Seq from Microsoft.FSharp.Collections
val toList: source: 'T seq -> 'T list
Multiple items
module List from Microsoft.FSharp.Collections

--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T member IsEmpty: bool member Item: index: int -> 'T with get ...
val truncate: count: int -> list: 'T list -> 'T list
val map: mapping: ('T -> 'U) -> list: 'T list -> 'U list
val x: CsvProvider<...>.Row
property CsvProvider<...>.Row.Player: string with get
property CsvProvider<...>.Row.Nation: string with get
property CsvProvider<...>.Row.Team: string with get
property CsvProvider<...>.Row.League: string with get
property CsvProvider<...>.Row.Age: int with get
property CsvProvider<...>.Row.MatchesPlayed: int with get
property CsvProvider<...>.Row.GoalsScored: int with get
type PlayerAndNation = { Player: string Nation: string }
type PlayerAndNation2 = { PlayerName: string Nationality: string }
type PlayerAndTeam = { Player: string Team: string }
type PlayerAndLeague = { Player: string League: string }
type PlayerAndAge = { Player: string Age: int }
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
type PlayerAndMatchesPlayed = { Player: string MatchesPlayed: int }
type PlayerAndGoalsScored = { Player: string GoalsScored: int }
Multiple items
val float: value: 'T -> float (requires member op_Explicit)

--------------------
type float = System.Double

--------------------
type float<'Measure> = float
type PlayerAndAgePlus1Int = { Player: string AgePlus1Int: int }
type PlayerAndGls = { Player: string GoalsScored: int }
type PlayerAndGlsFloat = { Player: string GoalsScoredFloat: float }
type TeamRecord = { Player: string Nation: string League: string AgeNextYear: int HalfGoalsScored: float }

Type something to start searching.