2016-01-13 44 views
1

我试图在F#中做一些图。作为一个输入,我有CSV文件有一些可为空的值(例如可为空)。我试图用下面的代码表示图表:F#如何处理可空类型

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

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

System.InvalidOperationException:可为空的对象必须有一个值。

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

回答

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 

然后,您可以映射回plotable号码,使用List.choose提取None箱子。

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

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

module Option = 
    let fromNullable (n: _ Nullable) = 
     if n.HasValue 
     then Some n.Value 
     else None 
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