如何在F#中使用匹配Map元素?

时间:2019-01-03 22:13:04

标签: f#

我试图创建一个函数,将两个整数a,b作为输入,如果a = 1 b = 2则返回5,否则返回6,这就是我所做的:

let examplef (a:int), (b:int)=
    match a,b with
    |1,2 -> 5
    |_,_->6;;

出现此错误:“未定义模式识别符'examplef'。”

由于此代码中的错误,我问这个问题:

type Team = string 
type Goals = Goals of int 
type Points = Points of int 
type Fixture = Team * Team 
type Result = (Team * Goals) * (Team * Goals) 
type Table = Map<Team,Points>

let league =["Chelsea"; "Spurs"; "Liverpool"; "ManCity"; "ManUnited"; "Arsenal"; "Everton"; "Leicester"]

let pointsMade (a: Result)=
    match a with
    |((b,Goals bg),(c,Goals cg))-> if b<c then ((b,Points 0),(c, Points 3))
                                   elif b=c then ((b,Points 1),(c,Points 1))
                                   else ((b, Points 3),(c, Points 0))

尝试定义以下函数时出现错误:

let updateTable (t:Table, r: Result)= 
    let pointmade = pointsMade r
    match pointmade with
    |((f,Points s),(f1,Points s1))-> match Map.tryFind f t  Map.tryFind f1 t with
                                    |None, None -> t
                                    |Some Points x, Some Points y ->t .Add (f, Points s+x1) .Add(f1, Points s1+y1)

当我将鼠标悬停在第一个“ Map.tryFind ft”上时,它说:“此值不是函数,不能应用。此外,t .Add (f, Points s+x1) .Add(f1, Points s1+y1)出现错误,它说:“后继参数应用空格隔开,元组和涉及函数或方法应用程序的参数应加括号。” 请帮助

3 个答案:

答案 0 :(得分:1)

您似乎在混淆元组和咖喱参数。

带有单个元组参数的示例(需要括号)。

签名:int * int-> int

//let example1 (a: int, b:int) = 
let example1 (a, b) =
    match a, b with
    | 1, 2 -> 5
    | _    -> 6

//let example2 (t: int * int) =
let example2 t =
    match t with
    | 1, 2 -> 5
    | _    -> 6 

带有两个咖喱参数的示例:

签名:int-> int-> int

//let example3 (a: int) (b: int) = 
let example3 a b =
    match a, b with
    | 1, 2 -> 5
    | _    -> 6

答案 1 :(得分:1)

在您的“工作代码”中,在pointsMade函数中,您无需使用模式匹配,只需使用let绑定即可。

let pointsMade (r: Result) =
    let (t1, Goals g1), (t2, Goals g2) = r
    if g1 < g2 then (t1, Points 0), (t2, Points 3)
    elif g1 = g2 then (t1, Points 1), (t2, Points 1)
    else (t1, Points 3), (t2, Points 0)

还可以通过使用某些updateTable函数来更简洁地重写addPoints函数,以避免为每个团队重复相同的事情。

let addPoints (team: Team, Points points) (table: Table) =
    match Map.tryFind team table with
    | None            -> table
    | Some (Points p) -> Map.add team (Points (points + p)) table

let updateTable (table: Table, result: Result) =
    let pts1, pts2 = pointsMade result
    table |> addPoints pts1 |> addPoints pts2

答案 2 :(得分:0)

无论如何,有效的代码如下:

open System.Security.Cryptography
open System.Threading

type Team = string 
type Goals = Goals of int 
type Points = Points of int 
type Fixture = Team * Team 
type Result = (Team * Goals) * (Team * Goals) 
type Table = Map<Team,Points>

let league =["Chelsea"; "Spurs"; "Liverpool"; "ManCity"; "ManUnited"; "Arsenal"; "Everton"; "Leicester"]

let pointsMade (a: Result)=
    match a with
    |((b,Goals bg),(c,Goals cg))-> if bg<cg then ((b,Points 0),(c, Points 3))
                                   elif bg=cg then ((b,Points 1),(c,Points 1))
                                   else ((b, Points 3),(c, Points 0))

let initEntry (name:Team)=(name, Points 0) 

let initializeTable l = Map.ofList (List.map initEntry l)

let updateTable (t:Table, r: Result)= 
    let pointmade = pointsMade r
    match pointmade with
    |((f,Points s),(f1,Points s1))-> match Map.tryFind f t,  Map.tryFind f1 t with
                                     |None, None -> t
                                     |Some  x, Some  y-> match x,y with
                                                         | Points x1 , Points y1 -> t |> Map.add f (Points(x1+s)) |> Map.add f1 (Points (y1+s1))
                                     |None, Some y -> match y with 
                                                      | Points y1 -> t.Add(f,Points s) .Add(f1, Points (s1+y1))
                                     |Some x, None -> match x with 
                                                      | Points x1 -> t.Add(f,Points (s+x1)) .Add(f1, Points s1)       


let rec weekendUpdate (t:Table , rl:Result list)=
    match rl with
    |[]->t
    |ai::at-> weekendUpdate(updateTable(t,ai),at)

let rec seasonUpdate (t:Table, sll: Result list list)= 
    match sll with
    |[]->t
    |ah::at-> seasonUpdate(weekendUpdate(t,ah),at)

let less((s1,n1):Team * Points, (s2,n2):Team * Points) = 
    match n1,n2 with
    |Points m1,Points m2 ->if m1<m2 then true
                           else false

let rec myinsert item lst = 
    match lst with 
    | [] -> [item] 
    | x::xs -> if less(item,x) then x::(myinsert item xs) else item::lst                      

let rec isort lst = 
    match lst with 
    | [] -> [] 
    | x::xs -> myinsert x (isort xs)

let showStandings (t:Table) = isort (Map.toList t)