Соответствие типа F # - невозможно создать карту или запись соответствия - PullRequest
0 голосов
/ 17 мая 2018

Я пытался адаптировать пример WikiBooks для приема ввода и типов 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

Чего мне не хватает?

1 Ответ

0 голосов
/ 17 мая 2018

Вам нужно использовать кортеж для создания Map из List, поэтому вам вообще не нужен тип записи.Затем вы захотите сопоставить 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."

EDIT Чтобы показать продолжение использования типа записи:

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."
...