如何在C#项目中使用F#定义的类型

时间:2016-04-10 19:33:18

标签: c# f#

我在F#DLL中实现了F#For Fun和Profit的Designing for Correctness example,它的开头是这样的:

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
        ....

我现在正在尝试创建一个简单的C#控制台应用程序来使用它。我的期望是我可以做类似的事情:

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

但是,Add不是一种方法:

enter image description here

Intellisense告诉我AddMicrosoft.FSharp.Core.FSharpFunc<Foo.Item,Foo.Cart> Cart.Add

我不确定我是否做错了什么,错过了注释,或者我是否误解了C#和F#的互操作性。事实上,有没有办法在C#中无缝使用这个F#代码?

1 个答案:

答案 0 :(得分:3)

您的会员Add是一个属性,因此从C#开始,您会看到返回FSharpFunc的内容,这对您没什么帮助。你需要做的是让Add成为一个参数。

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

这只是答案的第一部分,你还需要处理可变性/不变性的问题。

因为您使用的是不可变数据,所以addItemToCart函数需要看起来像这样:

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

(我在您提供的页面上的示例中对此进行了简化,因此您可以轻松查看实际发生的情况。)

现在,函数addItemToCart在给出空车时会返回一个带有一个项目的活动购物车,当给出一个包含n个项目的活动购物车时,它会返回一个带有n + 1个项目的活动购物车,这样额外的item已添加到列表中。请注意,addItemToCart实际上并不会更新现有购物车的状态,每次您将购物车作为参数提供时,它会为您提供新购物车。

然后,你需要在C#中不可变地使用你的Cart

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