f# - F# 中的警告“此构造导致代码比类型注释指示的更通用”是什么意思
问题描述
我有生成此警告的代码。
有一些与 SO 相关的帖子,最接近的是这个:这种结构导致代码比类型注释所指示的更通用
但我看不到它适用于何处,因为我的代码已经在函数中
所以,有问题的代码非常简单:
let exists (key: 'a) =
r.Exists(string key)
let set (key: 'a) value =
r.Set((string key), value)
let get (key: 'a) =
r.Get(string key)
let setDefault (key: 'a) value =
if not (exists key) then
set key value
我想要实现的是允许传递不同的枚举、字符串甚至整数作为键,并且,无论传递的类型是什么,它都会被转换为字符串(显然在合理范围内)
但是当我将该代码与枚举一起使用时,我会在标题中收到警告。
所以,我有两个问题:
- 我真的不明白这个警告。有人可以向我解释吗?
- 如何实现传递各种枚举或字符串并从中创建字符串键?
解决方案
问题来自使用string
. 如果您查看string 的源代码,您会看到它是inline
,这意味着编译器需要在编译时确定类型。在您的情况下,这意味着必须先解析泛型类型,然后string
才能调用,这反过来又迫使编译器选择可以工作的东西 - 在这种情况下,obj
.
有两种简单的方法可以解决这个问题 - 首先,您可以使您的函数内联,这允许编译器将其推迟到使用您的字符串的函数被使用。这在许多情况下都有效,但如果他们做与您正在做的事情相同的事情,也可能会在稍后将其“推到”给您的 API 使用者。这看起来像:
let inline set (key: 'a) value =
r.Set((string key), value)
另一种选择是避免使用string
运算符,并使用 .NET 中的所有对象包含的事实ToString
,并改为调用它:
let set (key: 'a) value =
r.Set(key.ToString()), value)
任何一种方法都将避免警告并保持功能通用。
推荐阅读
- google-cloud-platform - Microsoft Authenticode 代码签名 (EV) + Google Cloud HSM?
- python - IndexError ::: 列表索引超出范围
- android - 如何测试 gradle 插件构建速度的影响
- msbuild - 从 Build Pipeline 的 bin 文件夹中删除一个 DLL
- android - Android Studio 3.5 在我的智能手机上部署问题
- postgresql - 引起:org.springframework.beans.factory.BeanCreationException:使用Spring Boot 2创建名称错误的bean时出错
- angular-material - mat-form-field floatLabel="never" 不起作用
- haskell - 如何创建一个接受参数列表并返回将参数应用于另一个函数的函数的函数
- php - 使用函数作为 while 参数,如 Wordpress
- reactjs - 在 React 和 Typescript 中只允许特定组件作为子组件