繁体   English   中英

使用函数技术在F#中使用泛型重新实现C#继承

[英]Reimplementing C# Inheritance with generics in F# using functional techniques

我的抽象目标是:

1)创建一个CRUD API,它是带有CRUD接口的第三方库的包装器(可以来自服务对象和/或实体对象)

2)每个CRUD方法应根据预定义的类型定义限制输入的类型(一种类型可以输入多种方法)

3)当用户选择特定类型的方法时,他应该被迫根据所选类型插入正确类型的其他参数(如键),并且应该在编译时验证这些参数(将键作为对象类型传递需要运行时)评估对象的“真实”类型。

4)方法的类型是第三方接口,不在我的控制之下,我无法改变它们。

5)API对于用户来说应该是直截了当的,并且用户的样板代码量较少。

我发现在C#中解决这个问题的一种方法是:

public interface Update<T,TKey> {}
public interface Add<T> {}
public interface Delete<T,TKey> {}
public interface Get<T,TKey> {}

public class Invoice:Get<string>, Add<ThirdPartyInvoice>, Update<ThirdPartyInvoice,string> {}
//More types can come here...

public static class CRUDAPI
{
  public static T Get<T,TKey>(Get<T,TKey> type, TKey key)
  {
    //will get a T from a service object based on TKey
  }
  public static Unit Add<T>(Add<T> type, Func<T,T> select)
  {
    //will get a new instance of T and will feed it to the select function.
    //and then will feed the result to the 3rd party add method
  } 
  public static Unit Update<T,TKey>(Update<T,TKey> type,TKey key, Func<T,T> select)
  {
    //will load an instance of T and will feed it to the select function.
    //and then will feed the result to the 3rd party update method
  } 
  public static Unit Delete<T,TKey>(Delete<T,TKey> type,TKey key)
  {
    //will load an instance of T and then will use 3rd party delete method
  } 
}

然后用户可以使用它:

Add(new Invoice(), inv=> { inv.field1 = "123"; ... return inv;})

什么是以功能样式解决这个问题的好方法(例如在F#中)?

在函数式编程中,您可以使用泛型 代数类型来解决这个问题。 你通常会决定处理一个“命令”原语,如:

data Command a b c = Command(a -> Either b c)

您可以在命令的特异性,通用参数的数量和一般(进出)接口之间找到适当的平衡:尽管这两种方法都是经典选择,也可以在F#中使用; 另一种常用的类型是Maybe ,也是由F#提供的。

然后你可以定义:

data CRUD a b c d e f = CRUD{ create :: Command a b c, read :: Command d e f, ... }

再次找到合适的平衡点。

然后你弄清楚,有很多很多命令。 真。 其中一些直接进入数据库,其他负责DTO - >模型映射,其他处理验证。 你想用LEGO方式Command abc -> Command bed -> Command aed它们: Command abc -> Command bed -> Command aed ,这可以通过扩展你的Command代数类型来解决: ... | CompositeCommand(a -> Either bc, b -> Either ed) ... | CompositeCommand(a -> Either bc, b -> Either ed) ,内部依赖于Either的monadic绑定来链接两个函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM