gpt4 book ai didi

generics - 使包装的 F# SRTP 函数通用

转载 作者:行者123 更新时间:2023-12-02 08:05:19 27 4
gpt4 key购买 nike

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

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 操作的原因是因为这是 \ 和其他数学运算符的默认值。否则你会收到一个错误提示。

关于generics - 使包装的 F# SRTP 函数通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52168904/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com