具有通用参数类型的函数 [英] Functions with generic parameter types

查看:122
本文介绍了具有通用参数类型的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚如何定义一个可以处理多种类型参数的函数(例如int和int64)。据我了解,函数重载在F#中是不可能的(当然编译器会抱怨)。例如下面的函数。

  let sqrt_int = function 
| n:int - > int(sqrt(float n))
| n:int64 - > int64(sqrt(float n))

编译器当然会抱怨语法无效(类型约束在模式匹配中似乎不被支持),但我认为这说明了我想实现的功能:一个函数,它对多个参数类型进行操作并返回相应类型的值。我有一种感觉,这是可能的F#使用泛型/类型推理/模式匹配的一些组合,但语法已经躲过了我。我也尝试使用:?运算符(动态类型测试)和当在模式匹配块中使用子句时,但是这样仍会产生各种错误。



在语言方面,我可能很想在这里做一些不可能的事情,所以请让我知道是否有其他解决方案。 解决方案

p>重载通常是类型推导语言的bug(至少在类似F#的情况下,类型系统的功能不足以包含类型类)。在F#中有许多选择:


  • 在方法(类型的成员)上使用重载,在这种情况下,重载很有效就像在其他.Net语言中一样(您可以临时使用超载成员,提供的调用可以通过参数的数量/类型加以区分)
  • 使用inline,^和静态成员约束,用于在函数上进行特别重载(这是大多数需要处理int / float /等等的各种数学运算符;这里的语法很奇怪,除了F#库以外,这种语法很少使用)

  • 通过传递额外的操作字典参数来模拟类型类(这是INumeric在其中一个F#PowerPack库中对一般用于任意用户定义类型的各种数学算法进行的操作) li>
  • 返回到动态类型(传入'obj'参数,执行动态类型测试,为错误类型抛出运行时异常)


对于您的特定示例,我可能会说t使用方法重载:

  type MathOps = 
static member sqrt_int(x:int)= x |> float |> sqrt |> int
static member sqrt_int(x:int64)= x |> float |> sqrt |> int64

let x = MathOps.sqrt_int 9
let y = MathOps.sqrt_int 100L


I am trying to figure out how to define a function that works on multiple types of parameters (e.g. int and int64). As I understand it, function overloading is not possible in F# (certainly the compiler complains). Take for example the following function.

let sqrt_int = function
    | n:int   -> int (sqrt (float n))
    | n:int64 -> int64 (sqrt (float n))

The compiler of course complains that the syntax is invalid (type constraints in pattern matching are not supported it seems), though I think this illustrates what I would like to achieve: a function that operates on several parameter types and returns a value of the according type. I have a feeling that this is possible in F# using some combination of generic types/type inference/pattern matching, but the syntax has eluded me. I've also tried using the :? operator (dynamic type tests) and when clauses in the pattern matching block, but this still produces all sorts errors.

As I am rather new to the language, I may very well be trying to do something impossible here, so please let me know if there is alternative solution.

解决方案

Overloading is typically the bugaboo of type-inferenced languages (at least when, like F#, the type system isn't powerful enough to contain type-classes). There are a number of choices you have in F#:

  • Use overloading on methods (members of a type), in which case overloading works much like as in other .Net languages (you can ad-hoc overload members, provided calls can be distinguished by the number/type of parameters)
  • Use "inline", "^", and static member constraints for ad-hoc overloading on functions (this is what most of the various math operators that need to work on int/float/etc.; the syntax here is weird, this is little-used apart from the F# library)
  • Simulate type classes by passing an extra dictionary-of-operations parameter (this is what INumeric does in one of the F# PowerPack libraries to generalize various Math algorithms for arbitrary user-defined types)
  • Fall back to dynamic typing (pass in an 'obj' parameter, do a dynamic type test, throw a runtime exception for bad type)

For your particular example, I would probably just use method overloading:

type MathOps =
    static member sqrt_int(x:int) = x |> float |> sqrt |> int
    static member sqrt_int(x:int64) = x |> float |> sqrt |> int64

let x = MathOps.sqrt_int 9
let y = MathOps.sqrt_int 100L

这篇关于具有通用参数类型的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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