F#如何处理可空类型

时间:2016-01-13 17:13:05

标签: f#

我尝试在F#中做一些图表。作为输入,我有CSV文件,其中有一些值可以为空(例如nullable int)。我尝试使用以下代码显示图表:

[for row in data.Rows -> row.A.Value, row.B.Value] |> Chart.Point

A和B都是可以为空的整数。我收到以下错误

  

System.InvalidOperationException:Nullable对象必须具有值。

我应该如何处理可空类型。我应该写一些Option类型来处理它,或者还有其他一些好的方法来解决它。

3 个答案:

答案 0 :(得分:4)

如果您使用的是F#4.0,则内置函数Option.ofNullable。如果不是,那么您可以在其他答案中使用该实现。

您也可以使用相同的代码来定义活动模式:

let (|Present|_|) (n:System.Nullable<_>) = 
  if n.HasValue then Some(n.Value)
  else None

...这可以在match构造中使用,因此您可以编写:

[ for row in data.Rows do
    match row.A, row.B wih
    | Present a, Present b -> yield a,b 
    | _ -> () ] |> Chart.Point

答案 1 :(得分:3)

将Nullable类型映射到Option类型并将其过滤掉(使用.filter或.choose)或将None转换为缺失值的特殊值(例如0,-1,NaN),具体取决于您的数据以使其工作在图表工具中。

module Option =
   let fromNullable (n: _ Nullable) =
       if n.HasValue
       then Some n.Value
       else None

答案 2 :(得分:3)

你出错的地方是:你在可能为空的东西上调用Value属性。

当你打电话给Value时,你实际上是在说“没关系,我已经严格改变了这个值,并且它绝对不是空的所以把它当作非非法处理是完全安全的 - 可以接受的价值。“当然,在这种情况下,不满足该条件,因此运行时异常。

在F#中,您不想使用Nullable<'T>类型,您希望使用Option<'T>,这样更安全,编译器可以更有效地检查您是不是犯了错误。

您可以使用

将列表从Nullable<'T>转换为Option<'T>
[for row in data.Rows -> Option.ofNullable (row.A), Option.ofNullable(row.B)]

当然,你必须决定如何处理None个案,但是一旦你的设计明确地告诉你你有可能或者可能的值,那么这样做会容易得多不是什么。

我不知道你想要什么行为但是,作为一个例子,也许您只想绘制两个值都有效的情况?

您可以压缩两个选项值:

module Option =
    let zip a b =
        match (a,b) with
        |Some sa, Some sb -> Some(sa, sb)
        |_ -> None

然后,您可以回映到可绘制的数字,使用None提取List.choose个案例。

[for row in data.Rows -> Option.ofNullable (row.A), Option.ofNullable (row.B)]
|> List.choose (fun (a,b) -> Option.zip a b)
|> Chart.Point
相关问题