代码之家  ›  专栏  ›  技术社区  ›  matekus

F#类型匹配-无法创建映射或匹配记录

  •  2
  • matekus  · 技术社区  · 6 年前

    我曾尝试改编一个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 回复  |  直到 6 年前
        1
  •  5
  •   Aaron M. Eshbach    6 年前

    您需要使用元组来创建 Map List ,因此您根本不需要记录类型。然后,您将要匹配 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."