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
|
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.
|
- Transform each element of the
playerStatsTable
List into a tuple with the player and team (Player
,Team
)
answerplayerStatsTable
|> 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")]
- Transform each element of the
playerStatsTable
List into a tuple with the player and league/competiton (Player
,League
)
answerplayerStatsTable
|> 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")]
- Transform each element of the
playerStatsTable
List into a tuple with the player and age (Player
,Age
)
answerplayerStatsTable
|> 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)]
- Transform each element of the
playerStatsTable
List into a tuple with the player and matches played (Player
,MatchesPlayed
)
answerplayerStatsTable
|> 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)]
- Transform each element of the
playerStatsTable
List into a tuple with the player and goals scored (Player
,GoalsScored
)
answerplayerStatsTable
|> 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:
string
, example:"hello world"
int
, example:2
float
, example:2.0
decimal
, example:2.0m
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.
|
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 })
-
Define a record named
PlayerAndTeam
with a field namedPlayer
that is astring
andTeam
that is astring
. Then transform each element of theplayerStatsTable
List into aPlayerAndTeam
record.
answertype 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" }]
-
Define a record named
PlayerAndLeague
with a field namedPlayer
that is astring
andLeague
that is astring
. Then transform each element of theplayerStatsTable
List into aPlayerAndLeague
record.
answertype 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" }]
-
Define a record named
PlayerAndAge
with a field namedPlayer
that is astring
andAge
that is a integer(int
). Then transform each element of theplayerStatsTable
List into aPlayerAndAge
record.
answertype 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 }]
-
Define a record named
PlayerAndMatchesPlayed
with a field namedPlayer
that is astring
andMatchesPlayed
that is a integer(int
). Then transform each element of theplayerStatsTable
List into aPlayerAndMatchesPlayed
record.
answertype 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 }]
-
Define a record named
PlayerAndGoalsScored
with a field namedPlayer
that is astring
andGoalsScored
that is a integer(int
). Then transform each element of theplayerStatsTable
List into aPlayerAndGoalsScored
record.
answertype 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.
|
- Transform each element of the
playerStatsTable
List into an anonymous record with aPlayer
field that is astring
and aTeam
field that is astring
.
answerplayerStatsTable
|> 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" }]
- Transform each element of the
playerStatsTable
List into an anonymous record with aPlayer
field that is astring
and aLeague
field that is astring
.
answerplayerStatsTable
|> 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" }]
- Transform each element of the
playerStatsTable
List into an anonymous record with aPlayer
field that is astring
and aAge
field that is a integer(int
).
answerplayerStatsTable
|> 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" }]
- Transform each element of the
playerStatsTable
List into an anonymous record with aPlayer
field that is astring
and aMatchesPlayed
field that is a integer(int
).
answerplayerStatsTable
|> 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" }]
- Transform each element of the
playerStatsTable
List into an anonymous record with aPlayer
field that is astring
and aGoalsScored
field that is a integer(int
).
answerplayerStatsTable
|> 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.
|
When to use integers or floats/decimals:
- Use integers if the results of the calculations should be integers (1, 2, 3, 4, ...).
- Use floats or decimals if the results of the calculations may be floats or decimals (1.1, 2.1324, ...).
- map the
playerStatsTable
to a tuple of player and goals scored, but multiply goals scored by 10. (Player
,GoalsScored * 10
)
answerplayerStatsTable
|> 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)]
- map the
playerStatsTable
to a tuple of player and goals scored, but divide GoalsScored by 2. (Player
,GoalsScored / 2
)
answerplayerStatsTable
|> 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.
|
- map the
playerStatsTable
to a tuple of player and goals scored, but convert goalsScored to float. (Player
,float GoalsScored
)
answerplayerStatsTable
|> 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)]
-
map the
playerStatsTable
to a tuple of player and goals scored, but divide goalsScored by 2.0. (Player
,GoalsScored / 2.0
) Hint: convert goals scored to float and divide by 2.0 (you can't divide by 2 because if you perform math operations with different types, you'll get an error).
answerplayerStatsTable
|> 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.
|
-
map the
playerStatsTable
to a record of player and goals scored, but multiply goals scored by 10. (Player
,GoalsScored * 10
) Hint: You have to create a new type record.
answertype 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 }]
-
map the
playerStatsTable
to a record of player and goals scored, but divide goals scored by 2.0. (Player
,float GoalsScored / 2.0
)
Hint: You have to create a new type record, because previous type has goals scored as integers but you want floats.
answertype 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.
|
// 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.
|
- map the
playerStatsTable
to an anonymous record of player and goals scored, but multiply goals scored by 10. (Player
,GoalsScored * 10
)
answerplayerStatsTable
|> 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" }]
-
map the
playerStatsTable
to an anonymous record of player and goals scored, but divide goals scored by 2.0. (Player
,float GoalsScored / 2.0
)
Hint: Remember that you have to transform GoalsScored to float.
answerplayerStatsTable
|> 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:
- Player (
Player
) - typestring
- Nation (
Nation
) - typestring
- League (
League
) - typestring
- AgeNextYear (
Age + 1
) - typeint
- HalfGoalsScored (
GoalsScored / 2.0
) - typefloat
Hint: Create a new type.
answertype 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 string: value: 'T -> string
--------------------
type string = System.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
namespace FSharp
--------------------
namespace Microsoft.FSharp
namespace FSharp.Data
--------------------
namespace Microsoft.FSharp.Data
type LiteralAttribute = inherit Attribute new: unit -> LiteralAttribute
--------------------
new: unit -> LiteralAttribute
<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<unit>)</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>
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 int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
val float: value: 'T -> float (requires member op_Explicit)
--------------------
type float = System.Double
--------------------
type float<'Measure> = float