f# - 编译器无法从共享的“头”文件中解析类型
问题描述
在 Common.fs 中:
namespace Bug
module Common =
type SourceEntity = {
id : int
link : string
}
type ReleaseEntity = {
id : int
notes : string
}
在 Release.fs
namespace Bug
open System
open Common
module Release =
let cache = new Collections.Generic.Dictionary<int, ReleaseEntity>()
let AddToCache(entity) =
cache.Add(entity.id, entity)
()
let AddRec() =
let entity : ReleaseEntity = {
id = 1
notes = "Notes"
}
AddToCache(entity)
在 Source.fs 中
namespace Bug
open System
open Common
module Source =
let Cache = new Collections.Generic.Dictionary<int, SourceEntity>()
let AddToCache(entity) =
Cache.Add(entity.id, entity) <<=== E R R O R
()
let AddRec() =
let ent : SourceEntity = {
id = 1
releases = "Releases"
}
AddToCache(ent) <<=== E R R O R
Visual Studio 项目中按上述顺序包含的文件。
Source.fs 中报告的错误:错误 FS0001 此表达式应具有“SourceEntity”类型,
但此处具有“ReleaseEntity”类型
如果Common.fs中两种类型的顺序颠倒,Release.fs中报错,其中预期类型为ReleaseEntity,但类型为SourceEntity。
任何想法为什么会发生此错误?
解决方案
当您遇到类型错误时,请尝试考虑编译器是如何推断该特定类型的。
这里:
let AddToCache(entity) =
cache.Add(entity.id, entity)
()
编译器能知道哪个类型有一个id
字段entity
吗?如果您输入了
let entity = { id = 1; link = "" }
编译器会推断这是SourceEntity
因为只有SourceEntity
那些特定的记录字段。在cache.Add(entity.id, entity)
中,编译器没有其他约束,除了它必须有一个id
字段,所以它选择最后一个匹配类型 - 这就是你得到错误的原因。
如果将公共 id 字段重构为
namespace Bug
module Common =
type SourceEntity = {
source_id : int
link : string
}
type ReleaseEntity = {
release_id : int
notes : string
}
你会发现错误消失了。
解决方案
所有解决方案都涉及将其限制为已知类型。
最简单的就是添加类型注解:
let AddToCache(entity: SourceEntity) =
另一个是明确地解构它:
let { SourceEntity.id = id } = entity
Cache.Add(id, entity)
另一个是强制类型 - 这在这里不相关,但它可能会在未来变得有用:
Cache.Add((entity :> SourceEntity).id, entity)
我推荐这篇来自 F# 的文章,以获得关于类型推断的乐趣和收益,以便很好地解释该过程。
附言
您实际上只需要一种类型的注释。其余的可以推断:)
module Source =
let Cache = new Collections.Generic.Dictionary<_, _>()
let AddToCache (entity: SourceEntity) =
Cache.Add(entity.id, entity)
()
let AddRec () =
let ent = {
id = 1
link = ""
}
AddToCache(ent)
推荐阅读
- rust-cargo - 如何指定cargo单独依赖的github地址?
- phoenix-live-view - 在 Phoenix Live View 中,删除项目会删除 phx-hook 放置的 DOM 元素
- javascript - 视图构造中的反应方法
- python - 如何获取变量的斜率并从存储的(使用 python pickle 序列化)ML 模型中截取
- javascript - 来自方法的未定义对象的返回值
- jquery - 如何在 MVC 和 Jquery 中使用 Render View Partial 方法下载多个 pdf?
- python - Pygame - 跳跃动画过快
- numbers - 有没有办法将范围之间的任何数字转换为 0-1 之间的浮点数?
- django-models - 在 django 使用内部连接模型时表不存在错误
- python - Pyspark:连接以相似名称开头的排序列