Eug*_*hev 7 f# functional-programming
对于背景:它是功能DI的变体.在Scott的帖子后,我写了一个翻译.扭曲的是我的翻译是通用的,并根据你提供给它的东西进行参数化.
出于测试目的,我想通过另一个口译员,其中就是抄袭 - 我怎么办?以下是问题的简化概述:
let y f =
let a = f 1
let b = f 2L
(a,b)
Run Code Online (Sandbox Code Playgroud)
f是我的通用解释器,但在这里它显然受到第一次使用的约束int -> 'a.在这个简化的场景中,我可以只传递两次解释器,但在我的实际实现中,类型空间相当大(基类型x3输出类型).
是否有一些F#机制可以让我这样做,没有太多的开销?
Fyo*_*kin 10
您不能在F#中使用函数执行此操作.函数作为值传递时会失去通用性.
但是,F#确实有一种机制可以做到这一点,虽然有点笨拙:接口.接口方法可以是通用的,因此您可以使用它们来包装您的泛型函数:
type Wrapper =
abstract member f<'a> : 'a -> 'a
let y (w: Wrapper) =
let a = w.f 1
let b = w.f 2L
(a, b)
let genericFn x = x
// Calling y:
y { new Wrapper with member __.f x = genericFn x }
Run Code Online (Sandbox Code Playgroud)
缺点是,你不能回到高阶函数,以免失去通用性.你必须有接口一直到海龟.例如,您无法通过将其抽象为函数来简化实例创建:
let mkWrapper f =
// no can do: `f` will be constrained to a non-generic type at this point
{ new Wrapper with member __.f x = f x }
Run Code Online (Sandbox Code Playgroud)
但是你可以在另一边提供一些便利.至少摆脱类型注释:
type Wrapper = abstract member f<'a> (x: 'a): 'a
let callF (w: Wrapper) x = w.f x
let y w =
let a = callF w 1
let b = callF w 2L
(a,b)
Run Code Online (Sandbox Code Playgroud)
(注意:上面的代码中可能存在轻微的语法错误,因为我正在手机上写字)
不确定您是否仍然感兴趣,因为您已经接受了答案,但是正如@Fyodorsoikin 所要求的那样,这是“静态”方式,这一切都发生在编译时,因此没有运行时开销:
let inline y f =
let a = f $ 1
let b = f $ 2L
(a, b)
type Double = Double with static member inline ($) (Double, x) = x + x
type Triple = Triple with static member inline ($) (Triple, x) = x + x + x
type ToList = ToList with static member ($) (ToList, x) = [x]
let res1 = y Double
let res2 = y Triple
let res3 = y ToList
Run Code Online (Sandbox Code Playgroud)
当我需要在任意结构上使用泛型函数时,我会使用这种技术,我使用单个方法“Invokable”来命名类型。
更新
要向函数添加参数,请将其添加到 DU,如下所示:
type Print<'a> = Print of 'a with
static member inline ($) (Print printer, x) = printer (string x)
let stdout (x:string) = System.Console.WriteLine x
let stderr (x:string) = System.Console.Error.WriteLine x
let res4 = y (Print stdout)
let res5 = y (Print stderr)
Run Code Online (Sandbox Code Playgroud)
这只是一个快速简单的示例代码,但这种方法可以改进:您可以使用方法名称而不是运算符,您可以避免在声明中重复 DU,并且您可以组合 Invokables。如果您对这些增强功能感兴趣,请告诉我。我之前在生产代码中使用了这种方法的改进,但从未遇到任何问题。