如何在一个简单的函数中实现自动泛化

Joe*_*Joe 3 f# automatic-generalization

我创建了以下运算符来帮助安全划分.

let (/!) a b = 
    if b = 0 then 0 
    else a / b
Run Code Online (Sandbox Code Playgroud)

问题是它只适用于整数,我希望这个函数可以处理任何数字原语(int,float,decimal等).

我已经完成了关于自动泛化的一些阅读,但它并没有完全沉入,而且我不确定这是否是正确的方向.

如何完成此运算符的推广?

谢谢,

Car*_*ten 8

嗨,这是一个隐藏的宝石,但你要找的是这个:

let inline (/!) (a : ^a) (b : ^a) : ^a = 
    if b = LanguagePrimitives.GenericZero 
    then LanguagePrimitives.GenericZero 
    else a / b
Run Code Online (Sandbox Code Playgroud)

顺便说一句:这有这种怪物类型:

val inline ( /! ) :
  a: ^a -> b: ^a ->  ^a
    when  ^a : equality and  ^a : (static member get_Zero : ->  ^a) and
          ^a : (static member ( / ) :  ^a *  ^a ->  ^a)
Run Code Online (Sandbox Code Playgroud)

(这就是为什么我真的不想在声明中写这个;))

正如你所看到的那样,支持通用数字代码,但它并不经常讨论(F#有一些类似于类的东西 - 这是一个例子,其他类似的东西comparable,等等)

Tomas写了一篇关于此的好文章:编写通用数字代码

PS你不需要^a- 但我喜欢写签名 - 即使你可以这样做:

let inline (/!) a b = 
    if b = LanguagePrimitives.GenericZero 
    then LanguagePrimitives.GenericZero 
    else a / b

val inline ( /! ) :
  a: ^a -> b: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( / ) :  ^a *  ^b ->  ^c) and
          ^b : (static member get_Zero : ->  ^b) and  ^b : equality and
          ^c : (static member get_Zero : ->  ^c)
Run Code Online (Sandbox Code Playgroud)

它对你没有好处,因为真正的除法运算符通常只对两个参数都有一种类型 - 正如我所说:我喜欢强调参数名称的类型;)

有趣的事实

你可以绕过这样的GenericZero事情:

> let inline (/!) a b = if b = (b-b) then (b-b) else a/b;;

val inline ( /! ) :
  a: ^a -> b: ^b ->  ^b
    when ( ^a or  ^b) : (static member ( / ) :  ^a *  ^b ->  ^b) and
          ^b : (static member ( - ) :  ^b *  ^b ->  ^b) and  ^b : equality
Run Code Online (Sandbox Code Playgroud)

(为了安全起见:你可能会遇到某些类型/数字的麻烦;))

  • 您可以通过注释返回类型来清理签名:`let inline(/!)(a:^ a)(b:^ a):^ a = ...` (2认同)