F#:算术运算符和多态性丢失(值限制?)

时间:2014-10-29 14:27:10

标签: f# parametric-polymorphism value-restriction adhoc-polymorphism

此代码无法编译:

let f = fun x y -> x <<< y // bit shift
let g = fun x y -> x <<< y

[<EntryPoint>]
let main _ =
  printfn "%d" <| f 1 10
  printfn "%d" <| f 1L 10 // error
  printfn "%d" <| g 1L 10
  0
(7,21): error FS0001: This expression was expected to have type
    int
but here has type
    int64

我想统一者在看到第一次出现时修复了与fg相关联的类型参数。什么支配这个过程?我认为这与“价值限制”非常相似,但fg已经完全扩展了!这是一个难题。

我肯定会想到在整数类型上使用ad-hoc多态来键入预定义运算符背后有一些黑魔法,但这只是我的推测。任何信息都赞赏。

2 个答案:

答案 0 :(得分:2)

通用数字编程是使用静态成员约束完成的,这些约束无法在.NET类型系统中表示。它们仅存在于F#中,因此必须标记为inline

您的代码可以这样写:

let inline f x y = x <<< y // bit shift
let inline g z y = z <<< y

[<EntryPoint>]
let main _ =
  printfn "%d" <| f 1 10
  printfn "%d" <| f 1L 10 // works too
  printfn "%d" <| g 1L 10
  0

有关MSDN的更多信息:
Inline Functions
Statically Resolved Type Parameters

答案 1 :(得分:1)

我认为这是F#如何执行函数参数的自动泛化。在第一次出现时,它推断函数'f'可以具有类型('a - &gt;'a - &gt;'a)但第二个外观与此签名不匹配,因为它具有不同的签名('b - &gt;' a - &gt;'a)因为它将int64和int视为不同的类型。

内联函数有时可以像@Daniel提到的那样解决这个问题

可以在此处找到更多信息:http://msdn.microsoft.com/en-us/library/dd233183.aspx

有关静态成员约束的更多信息可以在Tomas Petricek的这篇文章中找到: http://tomasp.net/blog/fsharp-generic-numeric.aspx/