通过Project Euler试图学习F#,我在为问题3编写解决方案时偶然发现了类似推断问题.
这是我写的:
let rec findLargestPrimeFactor p n =
if n = 1 then p
else
if n % p = 0 then findLargestPrimeFactor p (n/p)
else findLargestPrimeFactor (p+1) n
let result = findLargestPrimeFactor 2 600851475143L
Run Code Online (Sandbox Code Playgroud)
但是,编译器给出了以下错误:
error FS0001: This expression was expected to have type int but here has type int64
由于我希望从使用中findLargestPrimeFactor推断出使用的类型,我很惊讶地发现编译器似乎假设参数n是一个int,因为在函数的唯一调用是用int64完成的.
有人可以向我解释一下:
Jac*_* P. 11
findLargestPrimeFactor从使用中推断出类型.F#编译器以从上到下的方式执行类型推断,因此从函数中的用法推断出类型p和n(参数findLargestPrimeFactor).到编译器看到时let result = ...,参数类型已被推断为int.
最简单的解决方案是L在所有常量值上使用后缀,因此类型将推断为int64:
let rec findLargestPrimeFactor p n =
if n = 1L then p
else
if n % p = 0L then findLargestPrimeFactor p (n/p)
else findLargestPrimeFactor (p + 1L) n
let result = findLargestPrimeFactor 2L 600851475143L
Run Code Online (Sandbox Code Playgroud)
如果您想要更高级的解决方案,可以使用LanguagePrimitives模块中的通用零和零常量.这允许findLargestPrimeFactor通用(-ish),因此可以使用不同的数字类型更轻松地重用它:
open LanguagePrimitives
let rec findLargestPrimeFactor p n =
if n = GenericOne then p
else
if n % p = GenericZero then findLargestPrimeFactor p (n/p)
else findLargestPrimeFactor (p + GenericOne) n
(* You can use one of these, but not both at the same time --
now the types of the _arguments_ are used to infer the types
of 'p' and 'n'. *)
//let result = findLargestPrimeFactor 2L 600851475143L
let result = findLargestPrimeFactor 2 Int32.MaxValue
Run Code Online (Sandbox Code Playgroud)
按@kvb的建议,这里是你如何编写这个函数的一般方法:
open LanguagePrimitives
let inline findLargestPrimeFactor p n =
let rec findLargestPrimeFactor p n =
if n = GenericOne then p
else
if n % p = GenericZero then findLargestPrimeFactor p (n/p)
else findLargestPrimeFactor (p + GenericOne) n
findLargestPrimeFactor p n
(* Now you can call the function with different argument types
as long as the generic constraints are satisfied. *)
let result = findLargestPrimeFactor 2L 600851475143L
let result' = findLargestPrimeFactor 2 Int32.MaxValue
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
674 次 |
| 最近记录: |