为两个或更多模块强制执行单一合同

gen*_*per 1 f#

F#中是否有任何支持的方法允许人们定义类似于可能需要实现两个或更多模块的接口的东西?例如,假设我定义了算法alg_1,alg_2,....,alg_n的集合,然后在module_a中定义相应的函数值.接下来,在module_b中,我还实现了alg_1,alg_2,...,alg_n(以不同的方式,可能用于测试目的).因此,module_a和module_b的"签名"完全相同,我希望使用相同的代码来执行函数,而不管module_a或module_b是否在范围内.

使用OO技术/接口(在F#/ C#/等中)这很简单; 使用F#中的功能技术处理这种情况的最佳方法是什么?是否有不同的方式来考虑更有效率的问题?

Tom*_*cek 6

您可以使用.fsi文件在F#中定义模块签名,但是您无法在运行时在模块的多个实现之间进行选择,因此在相同抽象接口的实现之间进行选择的可用性有限.

但是,F#将函数式编程与面向对象的编程结合起来,当它们很适合时,使用来自两个世界的概念是完全正确的 - 所以如果你想在运行时选择算法,我认为接口提供了最好的解决方案.

即使使用接口,您仍然可以使用非常实用的样式.假设你有一个界面:

type IAlgorithms =
  abstract Distance : float * float -> float
  abstract Compare : float * float -> bool
Run Code Online (Sandbox Code Playgroud)

您的两个模块可以包含像往常一样实现不同功能的功能.然后,您可以添加一个返回接口实现的值(并以可重用的方式公开功能):

module MyAlgorithms = 
  let distance a b = sqrt ((a - b) * (a - b))
  let compare a b = a < b

  let algorithms = 
    { new IAlgorithms with
        member x.Distance(a, b) = distance a b
        member x.Compare(a, b) = compare a b}
Run Code Online (Sandbox Code Playgroud)

在这里,我使用对象表达式来实现IAlgorithms接口 - 这比在类中包装所有内容要容易一些.

但这实际上取决于具体情况,所以这种方法可能会或可能不适合你!