Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 使包装的F#SRTP函数通用_Generics_Logging_F#_Inline - Fatal编程技术网

Generics 使包装的F#SRTP函数通用

Generics 使包装的F#SRTP函数通用,generics,logging,f#,inline,Generics,Logging,F#,Inline,我有一个使用静态解析类型参数的泛型函数 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,而不

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

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
操作的原因是,这是
\
和其他数学运算符的默认值。否则,您将得到一个表示歧义的错误。

现在您这样说,这是非常明显的。谢谢一路上都是乌龟。