0

此代码无法编译:

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

我猜统一器修复了与它们第一次出现相关联的类型f参数g。是什么支配了这个过程?我认为这与“价值限制”非常相似,但f已经g被 eta 扩展了!这是一个难题。

我肯定会想象在整数类型上键入具有临时多态性的预定义运算符背后有一些黑魔法,但这只是我的猜测。任何信息表示赞赏。

4

2 回答 2

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 的更多信息:
内联函数
静态解析类型参数

于 2014-10-29T14:54:57.273 回答
1

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

正如@Daniel 提到的,内联函数有时可以解决这个问题

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

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

于 2014-10-29T15:03:17.777 回答