尝试在f#中验证CSV数据

时间:2016-04-20 05:37:18

标签: f# type-providers

只是试着绕过一些F#,我遇到了问题。

我有一个类似

的CSV文件
CorrelationId,TagNumber,Description,CreationDate,UpdateDate,Discipline
8D3F96F3-938F-4599-BCA1-66B13199A39A,Test 70-2,Test tag - Ignore,2016-04-05 14:55:23.503,2016-04-05 14:55:23.503,Mechanical
A9FD4B9D-F7A1-4B7D-917F-D633EA0321E3,test-4,A test tag 24,2016-03-23 15:09:54.667,2016-03-30 17:35:29.553,Civil

我正在使用CSV类型提供程序

阅读它
open FSharp.Data
type Tag = CsvProvider<"tags.csv">
let readTags (path:string) =
    let tags = Tag.Load(path)

    printfn "%i" ( tags.Rows |> Seq.length )
    let tag = tags.Rows |> Seq.head

然后我想验证行,所以我从fsharpforfunandprofit铁路导向编程中提示。

type Result<'TSuccess,'TFailure> = 
| Success of 'TSuccess
| Failure of 'TFailure

let bind switchFunction twoTrackInput = 
    match twoTrackInput with
    | Success s -> switchFunction s
    | Failure f -> Failure f

let validateTagName tag = 
    if String.length tag.TagNumber = 0 then Failure "Tag number cannot be empty"
    else Success tag

let validateTagDescription tag  = 
    if String.length tag.Description = 0 then Failure "Tag description cannot be empty"
    else Success tag

但是我在验证方法中遇到了一个问题,我需要用类型注释函数。我不知道注释这些类型的类型。我尝试使用创建新类型并映射到它

type tagType = { TagNumber: string; Description: string}

这使得这些函数可以正常编译,但我刚刚将问题解决了,因为现在我不确定如何从Tag.Row映射到tagType。理想情况下,我无需进行任何映射即可进行此验证。

这一切应该怎么样?

2 个答案:

答案 0 :(得分:5)

您已从类型提供程序中获得Tag类型。使用该特定数据样本,它提供了一个名为Tag.Row的嵌套类型。您可以使用该类型注释您的函数:

let validateTagName (tag : Tag.Row) = 
    if String.length tag.TagNumber = 0 then Failure "Tag number cannot be empty"
    else Success tag

let validateTagDescription (tag : Tag.Row)  = 
    if String.length tag.Description = 0 then Failure "Tag description cannot be empty"
    else Success tag

这些函数编译。

答案 1 :(得分:3)

要添加Mark的答案,问题是以OOP方式打入一个类通常需要一个类型注释, 因为类型推断通常无法分辨出正在使用的类型。

例如,x的类型是什么?

let doSomething x = x.Length    // error FS0072: Lookup on object of indeterminate type 

使用附加到模块的函数可以为类型推断提供所需的信息:

let doSomething x = List.length x   // Compiles OK

类型推断通常适用于您定义的记录类型:

type tagType = { TagNumber: string; Description: string}
let doSomething x =  x.TagNumber // Compiles OK

但是在这种情况下,您正在使用由类型提供程序定义的类,因此类型推断也不起作用。

正如马克所说,最简单的方法是按照他演示的方式使用类型注释。

另一种方法是将类型提供程序Tag类型的转换函数写入您自己的MyTag类型,然后执行

let myTags = tags.Rows |> Seq.map convertToMyTag

将每一行转换为您的类型。当我想要一个更复杂的域类型而不仅仅是一个带字段的简单记录时,我有时会这样做。

在这种情况下,这将是过度的(你仍然需要在转换器函数中添加注释!)

最后,这里有两篇可能有用的帖子:understanding type inferencetroubleshooting common compiler errors