【问题标题】:How to implement automatic generalization in a simple function如何在一个简单的函数中实现自动泛化
【发布时间】:2014-08-28 16:32:27
【问题描述】:

我创建了以下运算符来帮助安全除法。

let (/!) a b = 
    if b = 0 then 0 
    else a / b

问题在于它只适用于整数,我希望这个函数适用于任何数字基元(int、float、decimal 等...)。

我已经阅读了一些关于自动泛化的文章,但还没有深入了解,我不确定这是否是正确的方向。

如何完成对这个算子的泛化?

谢谢,

【问题讨论】:

    标签: f# automatic-generalization


    【解决方案1】:

    您好,这是一个隐藏的宝石,但您正在寻找的是:

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

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

    val inline ( /! ) :
      a: ^a -> b: ^a ->  ^a
        when  ^a : equality and  ^a : (static member get_Zero : ->  ^a) and
              ^a : (static member ( / ) :  ^a *  ^a ->  ^a)
    

    (这就是我不太喜欢在声明中写这个的原因;))

    如您所见,支持通用数字代码,但并不经常讨论(F# 有一些类型类,比如内置的东西 - 这是一个例子,其他的东西是 comparable 等)

    Tomas 写了一篇很好的文章:Writing generic numeric code

    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)
    

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

    有趣的事实

    你可以像这样绕过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
    

    (为了安全起见:您可能会在此处遇到某些类型/数字的问题;))

    【讨论】:

    • 可以通过注释返回类型来清理签名:let inline (/!) (a : ^a) (b : ^a) : ^a = ...
    • 哦,非常好!我真的很喜欢你在 GenericZero 周围的方式。这是非常有用的。谢谢!
    • 等等,“非常特殊的数字”是什么意思?现在你让我好奇了。
    • Tomas 文章中对此进行了解释 - 它可以帮助您分散约束 - 没有它,您最终将再次拥有 Ints
    • "静态解析类型参数只能在编写标记为inline的泛型函数时使用。"
    猜你喜欢
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2012-09-19
    • 2023-01-08
    相关资源
    最近更新 更多