2016-07-20 12 views
1

Ich versuche, diese C# Methode zu konvertieren, die Schnittstellen und Linq zu f # verwendet:C# zu f # Umwandlung mit Schnittstellen und Linq Aussagen

public static IEnumerable<ModelEngines> CurrentEngineBuilds(IEnumerable<CurrentModels> thisYearModels, DateTime startRunDate, DateTime endRunDate) 
     { 
      var engineOptions = 
       currentModelYear.SelectMany(c => c.Engines) 
        .Where(e => e.EngineProdStartDate >= startRunDate & e.EngineProdStopDate <= endRunDate); 
      return engineOptions; 
     } 

Bei dem Verfahren oben, ich bin eine Sammlung von engineOptions Rückkehr - Typ ist IEnumerable. Ich filtere die Sammlung, sodass die Sammlung nur EngineOptions mit einem bestimmten Produktionsbereich aus dem aktuellen Modelljahr enthält.

Ich habe diese raue, nicht arbeitende, Übersetzung unter:

let CurrentEngineBuilds : <IEnumerable<ModelEngines>> (thisYearModels : IEnumerable<CurrentModels>) (startRunDate : DateTime) (endRunDate : DateTime) = 
    query { 
     for engineOptions in currentModelYear.engineOptions do 
     where (engineOptions.EngineProdStartDate >= startRunDate and engineOptions.EngineProdEndDate >= endRunDate) 
     select (engineOptions)    
    } 
    engineOptions 

Diese Aufgabe ist komplizierter geworden, als ich erwartet hatte. Ich habe ein paar f # -Tutorials durchgelesen, um die Grundlagen zu verstehen, aber es scheint, dass alles, was mit Schnittstellen und/oder linq zu tun hat, ziemlich schwierig ist.

Einige Fragen habe ich:

  • Wie zum Teufel Sie mit Schnittstellen in f # arbeiten?
  • Gibt es ein F-Äquivalenz der SelectMany-Methode?

Irgendwelche Tipps, wie man diese C# zu f # Umwandlung macht?

Antwort

4

IEnumerable<'T> heißt seq<'T> in F #. Ich sehe keinen Grund, LINQ query Ausdrücke in diesem Fall zu verwenden; die mehr idiomatische # Übersetzung F würde the Seq module verwenden:

let CurrentEngineBuilds thisYearModels startRunDate endRunDate = 
    thisYearModels 
    //  v--- SelectMany 
    |> Seq.collect (fun c -> c.Engines) 
    //  v--- Where 
    |> Seq.filter (fun e -> 
     e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate) 

Wenn die Art der thisYearModels wird nicht automatisch geschlossen, können Sie es in der Funktionssignatur mit Anmerkungen versehen können:

let CurrentEngineBuilds (thisYearModels:seq<CurrentModels>) startRunDate endRunDate = ... 

oder im Körper:

let CurrentEngineBuilds thisYearModels startRunDate endRunDate = 
    (thisYearModels:seq<CurrentModels>) 
    |> Seq.collect (fun c -> c.Engines) 
    |> Seq.filter (fun e -> 
     e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate) 
// or 
let CurrentEngineBuilds thisYearModels startRunDate endRunDate = 
    thisYearModels 
    |> Seq.collect (fun (c:CurrentModels) -> c.Engines) 
    |> Seq.filter (fun e -> 
     e.EngineProdStartDate >= startRunDate && e.EngineProdStopDate <= endRunDate) 
+0

Danke! Ein paar Fragen. Ich nehme an (Spaß c -> c.Engines) Art der Syntax ist wie der C# Lambda-Operator? Was macht der Operator '|>? Nochmals vielen Dank ... – SkyeBoniwell

+2

@ 999cm999: Ja, das ist F # Syntax für ein Lambda. Der '|>' Operator ändert 'fv' in' v |> f' und ist Fis 'Redewendung für monadische Verkettung (Dokumentation ist [hier] (https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/ Operatoren.% 5b-h% 5d-% 5d% 5b't1, '% 5d-function-% 5bfsharp% 5d)). – ildjarn

3

Sie können LINQ in F # tatsächlich ohne irgendwelche Probleme verwenden. Hier ist ein fast direkter Anschluss Ihrer ursprünglichen Probe (Ich gehe davon aus, dass currentModelYear ein Typ ist, und Sie gemeint thisYearModels)

open System.Linq 
let currentEngineBuilds(thisYearModels:seq<CurrentModels>, startRunDate, endRunDate) = 
    let engineOptions = 
     thisYearModels 
      .SelectMany(fun e -> e.Engines) 
      .Where(fun e -> e.StartDate >= startRunDate && e.StopDate <= endRunDate) 
    engineOptions // return keyword not required 

Für die Zwecke dieses Themas können Sie denken seq<T> als Abkürzung für IEnumerable<T>.

Ich denke, dass Sie das Modul Seq besser für F # finden, da es F # Sprachfunktionen wie Tuples nutzen kann und bei der Typ-Inferenz helfen kann.

2

Der Operator |> oder "pipe" ist die idiomatische Methode von F # zum Anwenden einer Funktion auf einen Wert.

v |> f ist das selbe wie f v, wie bereits erwähnt.

Monadische Verkettung hingegen ist eine ganz andere Sache. Sie verwenden monadische Verkettung im query Berechnungsausdruck im ursprünglichen Post, und es ist auch idiomatische.

Hoffe, dass hilft, diese zwei (ziemlich komplexen) Konzepte in Ihrem Verständnis auseinander zu halten! :)