2016-03-25 9 views
1

Ich bin etwa 2 Stunden neu zu F # und habe einige Probleme herausfinden, wie man eine diskriminierte Union Typ, der entweder Func<DateTime, DateTime, Option<DateTime>, Option<DateTime>> oder TimeSpan sein kann.Discriminated Union of Func und TimeSpan für C#

namespace Test 

open System 

type FuncOrTimeSpan = 
    // Should this be written in a different way to be able to take fun (a, b, c) -> ...? 
    | Func of Func<DateTime, DateTime, Option<DateTime>, Option<DateTime>> 
    | TimeSpan of TimeSpan 

module ThingDoer 

    let (|ActiveThing|_|) input = Option.Some(1) 

    // Do I need to tell this function that I expect it to return FuncOrTimeSpan? 
    let ReturnEitherFuncOrTimeSpan input = 
    match input with 
    | "should return TimeSpan" -> FuncOrTimeSpan.TimeSpan(TimeSpan.FromSeconds(10)) 
    | ActiveThing number -> FuncOrTimeSpan.Func(fun (a, b, c) -> Option.Some(DateTime.Now)) 

Ich bin immer an für schreit: Diese Funktion zu viele Argumente übernimmt oder in einem Kontext verwendet, bei denen Funktion ist nicht zu erwarten.

Was kann ich tun, damit ich das Lambda an die FuncOrTimeSpan.Func weitergeben kann?

Auch sollte ich Func of Func<DateTime, DateTime, Option<DateTime> zu etwas wie Func of DateTime -> DateTime -> Option<DateTime> -> Option<DateTime> umschreiben? Ich habe keine Ahnung, was das bedeutet und es hat nicht geholfen, als ich es versuchte.

Ich sollte wahrscheinlich beachten, dass ich vorhabe, mit dieser Funktion von C# zu verbinden (aber vielleicht wird der C# -Teil, der damit verbunden werden sollte, auch in F # umgeschrieben, so dass Interop-Lösungen immer noch willkommen sind).

+0

Was versuchen Sie mit ActiveThing? –

+0

'ActiveThing' ist in Ordnung, es ist nur ein aktives Muster für die Übereinstimmungsklausel, kein Problem dort. Ich habe es 'ActiveThing' genannt, weil ich mich nicht an den Namen erinnern konnte und den Tab nicht finden konnte, wo ich darüber gelesen habe.Ich habe es auch falsch umgeschrieben, es ist jetzt bearbeitet. –

+0

@ TomášHübelbauer Es gibt ein Problem dort, weil diese Syntax für eine teilweise aktive Muster nicht korrekt ist. Siehe https://msdn.microsoft.com/en-us/library/dd233248.aspx#Anchor_2 – TheInnerLight

Antwort

3

Es ist ziemlich schwierig zu konvertieren, diese Frage zu beantworten, ohne zu wissen, was genau Ihre Absicht ist es so eine qualitative Beschreibung des Problems Sie versuchen würde zu lösen Sei mir behilflich, eine klare Antwort zu geben, aber ich werde mein Bestes geben.

Zunächst einmal sollten Sie Ihre Typdefinition wie folgt aussehen:

type FuncOrTimeSpan = 
    | Func of (DateTime -> DateTime -> Option<DateTime> -> Option<DateTime>) 
    | TimeSpan of TimeSpan 

ich nichts falsch mit Ihrem aktuellen Typdefinition sehen, aber es ist sehr ungewöhnlich F # Funktionen System.Func mit zu schreiben.

Wenn Sie statt curried Argumente fach vervielfachten wollte, würden Sie es wie folgt schreiben:

type FuncOrTimeSpan = 
    | Func of (DateTime * DateTime * Option<DateTime> -> Option<DateTime>) 
    | TimeSpan of TimeSpan 

Während Sie allerdings noch lernen, empfehle ich Ihnen zum ersten Stock, bis Sie die Unterschiede herausgefunden haben, . Im Grunde erlauben curied-Argumente eine bequeme partielle Anwendung, während Tupel-Argumente eine bequeme Gruppierung von Parametern/Rückgaben erlauben. Weitere Informationen zum Curry in F # finden Sie unter https://fsharpforfunandprofit.com/posts/currying/.

Wie dem auch sei, geht nach vorn mit der ersten Typdefinition, würde Ihre Funktion dann wie folgt aussehen:

let returnEitherFuncOrTimeSpan input = 
    match input with 
    | "should return TimeSpan" -> TimeSpan(TimeSpan.FromSeconds(10.0)) 
    | ActiveThing number -> Func(fun a b c -> Some(DateTime.Now)) 

Ich weiß nicht, warum Sie diese ActiveThing Teil aktiven Muster verwenden würde, da es nicht tun etwas. Es nimmt einfach jedes Argument und gibt Some 1 zurück, so dass Sie ebensogut einfach durch einen Platzhalter ersetzen können.

let returnEitherFuncOrTimeSpan input = 
    match input with 
    | "should return TimeSpan" -> TimeSpan(TimeSpan.FromSeconds(10.0)) 
    | _ -> Func(fun a b c -> Some(DateTime.Now)) 

Diese Funktion gibt einen algebraischen Datentyp entweder 1) eine Zeitspanne von 10 Sekunden, wenn man ihm die Zeichenfolge geben „zurückkehren sollte Span“ als Argument oder 2) eine curried Funktion vom Typ DateTime -> DateTime -> Option<DateTime> -> Option<DateTime> (was letztlich zurückkehrt enthält DateTime.Now für alle gelieferten Argumente).

+0

Oh, ich sehe, woher die Verwirrung kam, es tut mir sehr leid - das aktive Muster hat tatsächlich Dinge in meinem ursprünglichen Code gemacht, ich habe es nur der Kürze halber vereinfacht, aber ich wollte es lassen, falls es Auswirkungen auf die Antwort hatte . –

2

Sie benötigen das Curry Ergebnis einen System.Func

let ReturnEitherFuncOrTimeSpan input = 
    match input with 
    | "should return TimeSpan" -> 
     let timespan = TimeSpan.FromSeconds(10.0) 
     FuncOrTimeSpan.TimeSpan(timespan) 
    | ActiveThing number -> 
      let curryResult = fun (a : DateTime) (b:DateTime) (c:DateTime option) -> Some(DateTime.Now) 
      let funcResult = System.Func<_,_,_,_>(curryResult) 
      FuncOrTimeSpan.Func(funcResult) 
+0

Wenn dies Ihr Problem löst, dann müssen wir Markieren Sie diese Frage als Duplikat. –

+0

Sehr cool, danke für die Antwort. Ich habe beschlossen, @ TheInnerLights Antwort zu markieren, ich hoffe es stört dich nicht. Ich fand es, um Punkte zu liefern, die einige meiner Frage beantworteten, die ich nicht gefragt habe. Bitte markieren Sie die Frage auch als Duplikat, wenn Sie es nicht finden - ich habe kein Duplikat gefunden, weil der Mangel an Domänenwissen mich daran hindert, ausreichend zu googlen. Ich kenne keine der Begriffe, nach denen Sie suchen sollten. :) –

+2

Es stört mich überhaupt nicht. Wir sind hier um zu lernen. Ich hoffe du wirst F # genießen. Dies ist einer der besten Orte, um Fragen für F # zu stellen. Sie sollten sich das [F # info-Tag] anschauen (http://stackoverflow.com/tags/f%23/info). Die Schlüsselbegriffe, die ich zum Googlen verwendet habe, waren 'F # erwartet 'Func <" C# 'Wenn du es als Duplikat ansiehst, kannst du es selbst als Duplikat markieren. –