2016-04-10 20 views
2

I For Fun F # implementiert haben und davon profitieren die Designing for Correctness example in einer F # DLL, die wie folgt beginnt:Wie F # verwenden -defined Typen innerhalb eines C# Projekt

module Foo = 
    type Item = { Price : double; Name : string } 

    type EmptyState = NoItems 
    type ActiveState = { UnpaidItems : Item list } 
    type CompletedState = { PaidItems : Item list; PurchaseDate : System.DateTime } 

    type Cart = 
     | EmptyCart of EmptyState 
     | ActiveCart of ActiveState 
     | CompletedCart of CompletedState 

    .... 

    let addItemToCart cart item = 
     match cart with 
     | EmptyCart state -> state.Add item 
     | ActiveCart state -> state.Add item 
     | CompletedCart state -> 
      printfn "ERROR: The cart is paid for" 
      cart 
    ... 

    type Cart with 
     static member NewCart = Cart.EmptyCart NoItems 
     member this.Add = addItemToCart this 
     .... 

Ich versuche jetzt eine einfach zu erstellen C# Konsolen-App, um es zu benutzen. Meine Erwartung ist, dass ich so etwas tun kann:

var myCart = Foo.Cart.NewCart(); // implicitly creates an EmptyCart 

var item = new Foo.Item(123.45, "something"); 
myCart.Add(item); // adds a new item, changing to ActiveCart 
// do other stuff, like adding more items, deleting them, then completing the cart 

jedoch Add ist keine Methode:

enter image description here

Intellisense sagt mir, dass AddMicrosoft.FSharp.Core.FSharpFunc<Foo.Item,Foo.Cart> Cart.Add ist.

Ich bin mir nicht sicher, ob ich etwas falsch gemacht habe, eine Anmerkung fehlt oder ob ich die Interoperabilität von C# und F # falsch verstehe. Gibt es tatsächlich eine Möglichkeit, diesen F # -Code nahtlos in C# zu verwenden?

+0

Welche Mitglieder sagen IntelliSense, dass 'FSharpFunc' * * hat? –

+2

'Mitglied this.Add x = addItemToCart dieses x' – PetSerAl

+0

@MarkSeann: Nicht sicher, ich verstehe die Frage, aber' myCart' hat 'Add',' Display', 'IsActiveCart',' IsCompletedCart', 'IsEmptyCart',' Entfernen 'und' Tag' Eigenschaften. Mitgliedsfunktionen scheinen nur diejenigen zu sein, die für Objekte intrinsisch sind ('ToString',' Equals', usw.). – user655321

Antwort

3

Ihr Mitglied Add ist eine Eigenschaft, daher werden Sie von C# etwas sehen, das FSharpFunc zurückgibt, was Ihnen nicht viel helfen wird. Was Sie tun müssen, ist Add eine Methode machen, indem Sie es ein Argument nehmen.

type Cart with 
    static member NewCart = Cart.EmptyCart NoItems 
    member this.Add item = addItemToCart this item 

Das ist nur der erste Teil der Antwort, Sie müssen sich auch mit der Frage der Veränderlichkeit/Unveränderlichkeit befassen.

Weil Sie unveränderlichen Daten verwenden, Ihre addItemToCart Funktion muss so etwas wie folgt aussehen:

let addItemToCart cart item = 
    match cart with 
    | EmptyCart state -> ActiveCart {UnpaidItems = [item]} 
    | ActiveCart state -> ActiveCart {UnpaidItems = item :: state.UnpaidItems} 
    | CompletedCart state -> 
     printfn "ERROR: The cart is paid for" 
     cart 

(ich auf der Seite zur Verfügung gestellt Sie so können Sie sehen, das ist ein bisschen aus dem Beispiel vereinfacht habe leicht, was geht jetzt weiter.)

Nun gibt die Funktion addItemToCart, wenn ein leerer Warenkorb gegeben wird, einen aktiven Einkaufswagen mit einem Artikel zurück, und wenn ein aktiver Einkaufswagen mit n Artikeln gegeben wird, gibt es einen aktiven Einkaufswagen mit n + 1 Artikel zurück Der zusätzliche Artikel wird der Liste vorangestellt. Beachten Sie, dass addItemToCart nicht wirklich den Zustand des vorhandenen Wagens aktualisiert, jedes Mal, wenn Sie ihm einen Wagen als Argument geben, gibt es Ihnen einen neuen Wagen zurück.

Sie müssten dann Ihre Cart unveränderlich von C# auch verwenden.

var myCart = Foo.Cart.NewCart(); // creates an EmptyCart 
var item = new Foo.Item(123.45, "something"); 
var myUpdatedCart = myCart.Add(item); // adds a new item, returning a new ActiveCart 
+0

Ich glaube, das erste Problem war eine Annahme, dass 'member this.Add = addItemToCart this' curried (richtige Verwendung des Begriffs?) Der 'addItemToCart state item'. Die zweite, nachdem ich das angesprochen habe, war, dass der C# -Code 'myCart.Add (item)' in einer leeren 'myCart' resultierte. Ich bin mir nicht sicher, warum ich angenommen habe, dass "myCart" mutieren würde, aber wenn ich meinen Code in "myCart = myCart.Add (item)" ändere, gibt es das Verhalten, auf das ich gehofft hatte. – user655321