2016-04-20 9 views
4

Ich versuche nur, meinen Kopf um ein paar F # zu wickeln und ich habe ein Problem.Versucht, CSV-Daten in f zu validieren #

Ich habe eine CSV-Datei, die

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 

wie

aussieht Und ich bin es bei der Verwendung des Typ-Provider CSV Lesen

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 

Dann würde ich die Zeilen validieren möchten so nahm ich ein Tipp von der fsharpforfunandprofit bahnorientierten Programmierung.

Aber ich bekomme ein Problem in den Validierungsmethoden, die ich brauche, um die Funktionen mit einem Typ zu kommentieren. Ich habe keine Ahnung, um welchen Typ ich diese annotieren soll. Ich habe versucht, mit dem Erstellen eine neue Art und Mapping, um es

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

spielen, die diese Funktionen gemacht kompilieren richtig, aber ich trat das Problem nur auf der Straße, weil ich jetzt nicht sicher bin, wie von dem Tag.Row zur Karte zu TagTyp. Im Idealfall würde ich diese Validierung durchführen, ohne Mapping durchführen zu müssen.

Wie sollte das alles aussehen?

+0

Sie könnten einige Tricks mit Inline-Funktionen machen, die methodenbasierte Einschränkungen zulassen. –

Antwort

3

Um Marks Antwort hinzuzufügen, ist das Problem, dass das Punktieren in eine Klasse in der OOP-Art im Allgemeinen eine Typannotation benötigt, da die Typinferenz normalerweise nicht feststellen kann, welcher Typ verwendet wird.

Zum Beispiel, was ist der Typ von x hier?

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

eine Funktion zu einem Modul angebrachte Verwendung würde der Typinferenz die Informationen geben, es braucht:

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

Die Typinferenz normalerweise mit Datensatztypen arbeiten, die Sie definiert haben:

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

Aber in diesem Fall arbeiten Sie mit einer Klasse, die von einem Typ-Provider definiert wird, so dass die Typ-Inferenz nicht so gut funktioniert.

Wie Mark sagt, ist es am einfachsten, eine Typ-Anmerkung zu verwenden, so wie er es demonstriert.

Die Alternative wäre eine Konverterfunktion vom Typ Provider Tag Typ Ihrer eigenen MyTag Art zu schreiben, und dann tut

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

jede Zeile in Ihre Art zu konvertieren. Manchmal mache ich das, wenn ich einen anspruchsvolleren Domain-Typ als nur einen einfachen Datensatz mit Feldern möchte.

In diesem Szenario aber das wäre übertrieben (und müssen Sie noch eine Anmerkung zu der Konverterfunktion hinzuzufügen!)

Schließlich, hier sind zwei Beiträge, die nützlich sein könnten: understanding type inference und troubleshooting common compiler errors .

5

Sie haben bereits den Typ Tag vom Typ Provider. Mit diesem bestimmten Datensample wird ein verschachtelter Typ namens Tag.Row bereitgestellt. Sie können Ihre Funktionen mit diesem Typ annotieren:

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 

Diese Funktionen kompilieren.

+0

Oh mein Gott, ich hatte das an einem Punkt während meiner Stumplings, außer dass ich die Klammer um die Funktionsparameter vermisste. Vielen Dank – stimms

Verwandte Themen