将Seq.tryFind和x.IsSome组合在一行中

时间:2014-12-26 05:18:28

标签: text f# find

我正在尝试将与特定(可选)关键字相关联的数据从文件读取到F#中的不可变。

当文件中存在关键字时,我的代码会执行我想要的操作:

let variable1 = 
    lines 
    |> Seq.find(fun x -> x.Contains "keyword1") 
    |> fun x -> x.Split(']').[1]

如果关键字不存在,Seq.find会按预期中断。而不是使用tryFind几行,如果/然后我试图使它全部以F#方式在一行中工作,但我不知道如何处理tryFind的输出,因为后续的拆分操作需要类型字符串而不是比IsSome的未知类型。如何进一步满足红色波浪形需求的类型约束?

let variable1 = 
    lines 
    |> Seq.tryFind(fun x -> x.Contains "keyword1") 
    |> fun x -> if x.IsSome then x.Split(']').[1]

2 个答案:

答案 0 :(得分:5)

如果你只是想对一场比赛采取行动,Option.map就是你要走的路,正如ildjarn所提到的那样

let variable1 = 
    lines 
    |> Seq.tryFind(fun x -> x.Contains "keyword1") 
    |> Option.map (fun x -> x.Split(']')

或者,您可以使用地图/选择是否要对许多条目采取行动

let variables = 
    lines 
    |> Seq.map(fun x -> if x.Contains "keyword1" then Some x else None) 
    |> Seq.choose (fun x -> x.Split(']')

在任何情况下,then表达式的每个分支elseif .. then .. else ...的返回类型都需要 相同类型

两个分支的常见类型是 整个 表达式if .. then .. else ...的类型。这允许参考透明度,您可以随时插入一个复杂的表达式,其中接受一个更简单的表达式。

这是一个很大的自由,需要付出一点代价:你必须在两个分支中给出一个正确类型的表达式。

'例外'是你在一个计算表达式中定义了一些零,但即使在这种情况下,两个分支都提供,而不是由你...

答案 1 :(得分:4)

当你这样做时:

let variable1 = 
    lines 
    |> Seq.tryFind(fun x -> x.Contains "keyword1") 
    |>  fun x -> if x.IsSome then     x.Split(']').[1]

上一个x的类型为string option。我会做类似

的事情
let variable1 = 
    lines 
    |> Seq.tryFind(fun x -> x.Contains "keyword1") 
    |> function |Some(t) -> t.Split(']').[1] |None -> "" (*need a value for the None branch*)