【问题标题】:Why isn't my function generalized intuitively?为什么我的函数不能直观地概括?
【发布时间】:2012-03-20 01:55:06
【问题描述】:

我无法理解 F# 的类型推断器的行为。运算符string 依赖于编译时的静态类型分派,而不是运行时,这就是为什么像let lowerstring = string >> (fun s -> s.ToLowerInvariant()) 这样的东西没有被概括——编译器需要知道参数的类型。但是,我看到了一些奇怪的行为。

具有以下定义:

let inline lower (s: string) = s.ToLowerInvariant()

// 'T -> string, constrained to the type of its first use
let lowerstring1 = string >> lower

// Same as above
let lowerstring2 value = value |> string |> lower

// Same as above
let lowerstring3 = box >> string >> lower

// 'a -> string, fully generalized
let lowerstring4 value = value |> box |> string |> lower

我观察到这种行为:

// val token: JToken
// val num: int

let tokstr1 = lowerstring1 token // lowerstring1 now has type JToken -> string
let numstr1 = lowerstring1 num   // Error, doesn't compile

(* As above with lowerstring2 and lowerstring3 *)

let tokstr4 = lowerstring4 token // lowerstring4 now has type 'a -> string
let numstr4 = lowerstring4 num   // no error, works as 'expected'

我不清楚为什么 lowerstring3lowerstring4 的类型检查不同。静态约束似乎很可能,但如果是这种情况,那么lowerstring4 不应该无法概括吗?为什么函数参数的显式存在会在这里有所作为?

【问题讨论】:

  • 第一个是value,不能泛型;后者是一个函数,它可以。介绍inline 并享受一些真正的乐趣。

标签: types f# type-inference


【解决方案1】:

F# 必须将代码生成到 IL,并且由于 .NET 中没有通用“值”,因此只有当它们是真正的语法函数时才会生成函数(生成到可以是通用的 .NET 方法中)。

(一个例外是[<GeneralizableValueAttribute>],参见例如here。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    • 2016-04-10
    • 2015-01-05
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多