当我运行下面的代码时,我收到一个错误。我正在使用Map.TryFind并且它无法正常工作。在控制台中,我在familyinc.TryFind(tract)
下面出现一条红线,下面是错误。
let data =
seq { for (state,work) in statecsv do
let (family,income) = familyinc.TryFind(state)
let fam =
match fam with
| Some x -> x
| None -> "Not a Record"
let inc =
match inc with
| Some x -> x
| None -> "Not an income"
yield (state,work,inc,fam)
}
错误:
error FS0001: This expression was expected to have type
''a * 'b'
but here has type
'(string * decimal) option'
答案 0 :(得分:3)
回答编辑过的问题:问题与前一个问题相同,在绑定选项时,您在元组上进行模式匹配。你应该做这样的事情:
// Bind the whole option
let result = familyinc.TryFind(state)
// Pattern match on it
match result with
| Some (family , income) -> yield (state,work,family,income)
| None -> yield (state,work,"Not a Record","Not an Income")
当然你也可以做match familyinc.TryFind(tract) with
,这里不需要绑定变量。
问题是你对Map.TryFind()
的结果进行模式匹配,好像它会返回一个元组,但它实际上会返回一个option
,因为它可能无法找到你正在寻找的键。 / p>
答案 1 :(得分:1)
在所有FP语言中,了解选项类型和模式匹配至关重要。事实上,这两个特性使FP成为OO语言的优秀替代品。使用选项类型可以避免获得null
异常,使用模式匹配可以解构值。在这种情况下,您可以过滤掉不存在的密钥,并将option
结果转换为正常值:
//create test dictionary
let map1 = [("a",1); ("b",2);("c",3)] |> Map.ofList
//list of keys, "d" doesn't exist in the dictionary/map
let keys = ["a";"b";"d"]
keys
|> List.map (fun x -> map1.[x])
//System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
keys
|> List.map (fun x -> map1.TryFind(x))
//You get back a string option list, with the last element missing as the key "d" doesn't exist
//val it : int option list = [Some 1; Some 2; None]
//Method A: filter out the none existing items
keys
|> List.map (fun x -> map1.TryFind(x))
|> List.choose id //choose will get rid of the Nones and return the actual value, not the option. id is the identity function.
//Method B: replace the None with some default value, and also get rid of the option
//Let's say you replace each non existing value with 999
keys
|> List.map (fun x -> map1.TryFind(x))
|> List.map (Option.defaultValue 999)
//val it : int list = [1; 2; 999]
//In general if necessary you can always pattern match
let myOption1 = Some "A"
let myOption2 = None
match myOption1 with
| Some x -> x //try matching whatever is in myOption1 and returns the x portion of Some x, in this case "A"
| None -> "No value"
//val it : string = "A"
match myOption2 with
| Some x -> x
| None -> "No value" //since the value of myOption2 is None, Some x won't match, None will match, and return "No value"
//val it : string = "No value"