繁体   English   中英

使包装的F#SRTP函数通用

[英]Make wrapped F# SRTP function generic

我有一个使用静态解析类型参数的泛型函数

let inline divide a b = a / b

带有签名^a -> ^a -> ^a

我可以创建一个包装函数

let log f = 
    let result = f()
    printfn "Result: %A" result
    result

如果我再创建一个像

let loggedDivide a b = log (fun () -> divide a b)

它的签名是float -> float -> float而不是^a -> ^a -> ^a ,这意味着

loggedDivide 2.0 5.0
loggedDivide 2 5 //error

如何才能做到这一点?

注意,类似这样的东西错过了重用函数的意义

let logValue a = printfn "Result: %A" a
divide 2.0 5.0 |> logValue
divide 2 5 |> logValue

而且事情并没有保持这种通用性

let logValueAndReturn a = 
    printfn "Result: %A" a
    a

let divideAndLog a b = divide a b |> logValue
divideAndLog 2.0 5.0
divideAndLog 2 5 //error

您还必须使派生函数内联:

let inline loggedDivide a b = log (fun () -> divide a b)

这将使约束得以传播:

val inline loggedDivide :
  a: ^a -> b: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( / ) :  ^a *  ^b ->  ^c)

这样做的原因是SRTP是F#编译器功能,可在编译时解决,因此功能可以通过在调用站点内联来实现专门化。

如果您希望函数保持通用,则必须是内联的。

请注意,将函数推断为使用int操作的原因是,这是\\和其他数学运算符的默认设置。 否则,您将得到指示歧义的错误。

暂无
暂无

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

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