如何在F#中实现Abs,Sign等 [英] how are abs, sign etc implemented in F#

查看:93
本文介绍了如何在F#中实现Abs,Sign等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现:

abs -10
abs -10L

都工作.因此,我想知道F#如何实现此功能并在源代码中进行搜索:

both work. So I wondered how F# implemented this and did a search in the source code:

    type AbsDynamicImplTable<'T>() = 
    let AbsDynamic x            = AbsDynamicImplTable<_>.Result x

    [<CompiledName("Abs")>]
    let inline abs (x: ^T) : ^T = 
         AbsDynamic x
         when ^T : ^T = absImpl x

我对这些感到困惑.

正如我在abs这样的函数中所知道的,我们必须将输入与0进行比较,并且对于不同类型,它们具有不同的0.

As I know in a function like abs, we must compare the input with 0, and there are different 0s for different types.

谢谢.

推荐答案

要向ChaosPandion发布的代码添加一些解释,像abs这样的F#函数的问题在于它们可以与任何数字类型一起使用.仅使用F#/.NET泛型就无法表达这一点-唯一受支持的约束是类型参数实现某个接口或具有构造函数,但对数字类型没有任何约束.

To add some explanation to the code posted by ChaosPandion, the problem with F# functions like abs is that they can work with any numeric type. There is no way to express this just using F#/.NET generics - the only supported constrains are that type parameter implements a certain interface or has a constructor, but there is no constraint for numeric types.

因此,F#还支持静态约束(类型参数为^a而不是通常的'a),并且这些约束在编译时使用内联进行处理(这也解释了为什么函数必须为inline的原因).您可以使用LanguagePrimitives中的内置函数编写具有静态约束的自己的函数,该函数包含许多需要某些约束的有用函数:

So, F# also supports static constraints (the type parameter is ^a instead of usual 'a) and these are processed at compile time using inlining (this also explains why the function has to be inline). You can write you own function with static constraints by using built-in functions from LanguagePrimitives which contains many useful functions that require some constraints:

> let inline half (num: ^a) : ^a =
     LanguagePrimitives.DivideByInt< (^a) > num 2
  ;;
val inline half : ^a -> ^a 
   when ^a : (static member DivideByInt : ^a * int -> ^a)

> half 42.0;;
val it : float = 21.0

> half 42.0f;;
val it : float32 = 21.0f

请注意,可以推断出约束-DivideByInt要求类型具有DivideByInt成员,因此我们的函数也需要相同的东西(如果它也具有该成员,它将与您自己的类型一起使用,这非常有用! ).

Note that constraints are inferred - DivideByInt requires that the type has DivideByInt member, so our function requires the same thing (and it will work with your own type if it has this member too, which is quite useful!).

此外,abs的实现还使用了两个仅在F#库中允许的技巧-它为不同的类型(使用when ^a:int = ....)指定了不同的代码(用于内联时使用)和回退case,它使用Abs成员,因此它将与任何显式列出的类型或具有Abs成员的类型一起使用.另一个技巧是retype函数,该函数更改类型",但不包含任何代码-唯一的目的是进行代码类型检查,但这可能非常不安全-因此仅在F#中使用库.

In addition to this, the implementation of abs uses two additional tricks that are allowed only in the F# library - it specifies different code (to be used when inlining) for different types (using when ^a:int = ....) and a fallback case, which uses Abs member, so it will work with any explicitly listed type or a type with Abs member. Another trick is the retype function, which "changes the type", but doesn't contain any code - the only purpose is to make the code type-check, but this could be very unsafe - so this is used only in F# libraries.

这篇关于如何在F#中实现Abs,Sign等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆