Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
708 views
in Technique[技术] by (71.8m points)

f# - Functions with generic parameter types

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...