F#在实际处理int64时假设int [英] F# assuming int when actually dealing with int64

查看:88
本文介绍了F#在实际处理int64时假设int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试学习F#的过程中,经历了 Project Euler 的过程,我偶然发现了编写代码时似乎是类型推断的问题问题3 的解决方案.

Going through Project Euler trying to learn F#, I stumbled upon what appears to be a type inference problem while writing a solution for problem 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

但是,编译器给我以下错误:

However, the compiler gives me the following error:

error FS0001: This expression was expected to have type    int    but here has type    int64

由于我希望从用法中推断出findLargestPrimeFactor中使用的类型,所以我很惊讶地发现编译器似乎假设参数n是一个int,因为在对函数的唯一调用中就已经完成了带有int64.

Since I expect the types used in findLargestPrimeFactor to be inferred from usage, I'm quite surprised to find out the compiler seems to assume that parameter n be an int since in the only call to the function is done with an int64.

有人可以向我解释:

  1. 为什么编译器似乎对类型感到困惑
  2. 如何解决此限制

推荐答案

findLargestPrimeFactor中的类型是根据使用情况推断出来的. F#编译器以从上到下的方式执行类型推断,因此pn的类型(findLargestPrimeFactor的参数)是根据其在函数中的用法来推断的.到编译器看到let result = ...时,已经将参数类型推断为int.

The types in findLargestPrimeFactor are inferred from usage. The F# compiler performs type inference in a top-to-bottom manner, so the types of p and n (the parameters of findLargestPrimeFactor) are inferred from their usage in the function. By the time the compiler sees the let result = ..., the parameter types have already been inferred as int.

最简单的解决方案是在所有常量值上使用L后缀,因此类型将被推断为int64:

The easiest solution is to use the L suffix on all of your constant values, so the types will be inferred as 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

如果您想使用更高级的解决方案,则可以使用LanguagePrimitives模块中的通用一常数和零常数.这使得findLargestPrimeFactor可以是通用的(-ish),因此可以更轻松地将其与其他数字类型重用:

If you want a fancier solution, you can use the generic one and zero constants from the LanguagePrimitives module. This allows findLargestPrimeFactor to be generic(-ish) so it can be reused more easily with different numeric types:

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

按照@kvb的建议,以下是您如何通用地编写此函数的方法:

Per @kvb's suggestion, here's how you can write this function generically:

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

这篇关于F#在实际处理int64时假设int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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