我在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
不是一种方法:
Intellisense告诉我Add
是Microsoft.FSharp.Core.FSharpFunc<Foo.Item,Foo.Cart> Cart.Add
。
我不确定我是否做错了什么,错过了注释,或者我是否误解了C#和F#的互操作性。事实上,有没有办法在C#中无缝使用这个F#代码?
答案 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