F# 类型匹配 - 无法创建地图或匹配记录



我试图改编一个维基教科书示例以接受csv输入和类型,但我正在努力将传入的类型列表转换为字典并匹配用户输入。

// https://en.wikibooks.org/wiki/F_Sharp_Programming/Sets_and_Maps#Examples_2
module SOQN = 
open System
open FSharp.Data
type Country = Country of string
type City = City of string
type CountryCapital = {
Country:Country
City:City 
}
let [<Literal>] sampleCsv  = @"D:Country_Capitals.csv"
type Capitals = CsvProvider<sampleCsv, Separators=",", HasHeaders=true>
let readFromCsvFile (fileName:string) = 
let data = Capitals.Load(fileName)
[ for row in data.Rows do
yield { Country = Country row.Country; City = City row.City; } ]        
let countryCapitals = 
readFromCsvFile sampleCsv
// ->     |> Map.ofList
Console.Write("Find capital by country (type 'q' to quit): ")
match Console.ReadLine() with
| "q" -> Console.WriteLine("Bye!")
| country ->
match countryCapitals with
// ->     | { Country = country } -> Console.WriteLine("Capital of {0} is {1}n", country, capital)
| _ -> Console.WriteLine("Country not found.n")
// Expected Output: Find capital by country (type 'q' to quit): Egypt
//                  Capital of Egypt is Cairo

我错过了什么?

您需要使用元组从List创建Map,因此您根本不需要记录类型。 然后,您需要匹配输入国家/地区的Map.tryFind。 下面是一个使用元组和Map.tryFind的示例。 我所做的其他更改是使用printfn而不是Console.WriteLine并简化列表生成表达式:

open System
open FSharp.Data
let [<Literal>] sampleCsv  = @"D:Country_Capitals.csv"
type Capitals = CsvProvider<sampleCsv, Separators=",", HasHeaders=true>
let readFromCsvFile (fileName:string) = 
let data = Capitals.Load(fileName)
[ for row in data.Rows -> (row.Country, row.City) ]    
let countryCapitals = 
readFromCsvFile sampleCsv
|> Map.ofList
printfn "Find capital by country (type 'q' to quit): "
match Console.ReadLine() with
| "q" -> printfn "Bye!"
| country ->
match countryCapitals |> Map.tryFind country with
| Some capital -> printfn "Capital of %s is %s" country capital
| _ -> printfn "Country not found."

编辑要显示记录类型的继续使用,请执行以下操作:

open System
open FSharp.Data
type CountryCaptial = { Country: string; Capital: string }
let [<Literal>] sampleCsv  = @"D:Country_Capitals.csv"
type Capitals = CsvProvider<sampleCsv, Separators=",", HasHeaders=true>
let readFromCsvFile (fileName:string) = 
let data = Capitals.Load(fileName)
[ for row in data.Rows -> { Country = row.Country; Capital = row.City } ]    
let countryCapitals = 
readFromCsvFile sampleCsv
|> List.map (fun c -> c.Country, c)
|> Map.ofList
printfn "Find capital by country (type 'q' to quit): "
match Console.ReadLine() with
| "q" -> printfn "Bye!"
| country ->
match countryCapitals |> Map.tryFind country with
| Some countryCapital -> printfn "Capital of %s is %s" countryCapital.Country countryCapital.Capital
| _ -> printfn "Country not found."

最新更新