我有以下代码,这些代码会为这些可以解析的Url返回seq
DownloadLink
。
type DownloadLink = { Url: string; Period: DateTime }
nodes |> Seq.map (fun n ->
let url = n.Attributes.["href"].Value
match url with
| Helper.ParseRegex "[a-zA-Z](?<period>\d{4})\.txt" [period] ->
{ Url = url; Period = period }
| _ ->
printfn "Cannot parse %s" url // Error
)
但是,我在printfn
收到了以下错误。什么是正确的实施方式?我应先将list option
设为None
,然后过滤掉这些{{1}}项吗?
Error 1 Type mismatch. Expecting a string -> DownloadLink but given a string -> unit The type 'DownloadLink' does not match the type 'unit'
答案 0 :(得分:5)
基本问题是,如果你有像
这样的东西match x with
|true -> A
|false -> B
A
和B
的类型必须相同。
实际上有一个内置函数,它使用Some
组合了地图和过滤器 - 使用Seq.choose
就像这样
nodes |> Seq.choose (fun n ->
let url = n.Attributes.["href"].Value
match url with
| Helper.ParseRegex "[a-zA-Z](?<period>\d{4})\.txt" [period] ->
Some ({ Url = url; Period = period })
| _ ->
printfn "Cannot parse %s" url // Error
None
)
答案 1 :(得分:4)
除Seq.choose
之外,您还可以使用序列表达式很好地解决问题 - 您可以使用yield
在一个分支中返回结果,但不必在另一个分支中生成值:
seq { for n in nodes do
let url = n.Attributes.["href"].Value
match url with
| Helper.ParseRegex "[a-zA-Z](?<period>\d{4})\.txt" [period] ->
yield { Url = url; Period = period }
| _ ->
printfn "Cannot parse %s" url }
除此之外,我不建议将副作用(打印)作为处理代码的一部分。如果要报告错误,最好返回一个选项(或定义Success
或Error of string
类型),以便将错误报告与处理分开。