F# 编译器无法解析共享';标题';文件

F# 编译器无法解析共享';标题';文件,f#,F#,共同点。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 =

共同点。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)
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
名称空间错误
开放系统
开放式公用
模块释放=
let cache=new Collections.Generic.Dictionary()
让AddToCache(实体)=
cache.Add(entity.id,entity)
()
let AddRec()=
let实体:ReleaseEntity={
id=1
notes=“notes”
}
AddToCache(实体)
在Source.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)
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
名称空间错误
开放系统
开放式公用
模块源=
let Cache=new Collections.Generic.Dictionary()
让AddToCache(实体)=

Cache.Add(entity.id,entity)当您遇到类型错误时,请尝试思考编译器是如何推断特定类型的

在这里:

编译器是否可以知道哪种类型在
实体
中有一个
id
字段? 如果你输入了

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
    }
你会发现错误消失了

解决方案

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)
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
所有解决方案都涉及将其约束为已知类型

最简单的方法是添加类型注释:

let AddToCache(entity: SourceEntity) =
let AddToCache(entity) = 
    Cache.Add(entity.id, entity)
    ()
另一个是明确地解构它:

let { SourceEntity.id = id } = entity
Cache.Add(id, entity) 
另一种方法是强制类型-这与此处无关,但在以后可能会很有用:

Cache.Add((entity :> SourceEntity).id, entity) 
我建议从F#for fun and profit on type inference那里获得一个很好的过程解释

p.S.

实际上,您只需要一个类型注释。 其余的可以推断:)

模块源代码=
let Cache=new Collections.Generic.Dictionary()
let AddToCache(实体:SourceEntity)=
Cache.Add(entity.id,entity)
()
让AddRec()=
让ent={
id=1
link=“”
}
AddToCache(耳鼻喉科)

当您遇到类型错误时,请尝试思考编译器是如何推断出特定类型的

在这里:

编译器是否可以知道哪种类型在
实体
中有一个
id
字段? 如果你输入了

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
    }
你会发现错误消失了

解决方案

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)
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
所有解决方案都涉及将其约束为已知类型

最简单的方法是添加类型注释:

let AddToCache(entity: SourceEntity) =
let AddToCache(entity) = 
    Cache.Add(entity.id, entity)
    ()
另一个是明确地解构它:

let { SourceEntity.id = id } = entity
Cache.Add(id, entity) 
另一种方法是强制类型-这与此处无关,但在以后可能会很有用:

Cache.Add((entity :> SourceEntity).id, entity) 
我建议从F#for fun and profit on type inference那里获得一个很好的过程解释

p.S.

实际上,您只需要一个类型注释。 其余的可以推断:)

模块源代码=
let Cache=new Collections.Generic.Dictionary()
let AddToCache(实体:SourceEntity)=
Cache.Add(entity.id,entity)
()
让AddRec()=
让ent={
id=1
link=“”
}
AddToCache(耳鼻喉科)
这是记录字段名称的冲突(和阴影)

当您在
Bug.Source.AddToCache
的主体中写入
entity.id
时,编译器使用您正在访问
.id
字段的事实来推断
entity
的类型。哪些记录的字段名为
id
?这两条记录确实如此,但编译器必须选择一条。怎么用?简单:最后一个优先。这被称为“阴影”

为了消除选择的歧义,只需添加一个类型注释:

let AddToCache(entity: SourceEntity) =
let AddToCache(entity) = 
    Cache.Add(entity.id, entity)
    ()

等等,但是为什么编译器不使用
缓存的类型。添加
来推断
实体的类型

嗯,这只是F#的一个限制(或特征?)。编译是单遍的,类型干涉自上而下、从左到右进行,没有双回。这使得编译器能够非常快速且非常可预测(看看你,Haskell)

但在这种情况下,这意味着当编译器看到
实体
被用作
缓存.Add
中的参数时,它已经决定了它必须是什么类型。

这是记录字段名的冲突(和阴影)

当您在
Bug.Source.AddToCache
的主体中写入
entity.id
时,编译器使用您正在访问
.id
字段的事实来推断
entity
的类型。哪些记录的字段名为
id
?这两条记录确实如此,但编译器必须选择一条。怎么用?简单:最后一个优先。这被称为“阴影”

为了消除选择的歧义,只需添加一个类型注释:

let AddToCache(entity: SourceEntity) =
let AddToCache(entity) = 
    Cache.Add(entity.id, entity)
    ()

等等,但是为什么编译器不使用
缓存的类型。添加
来推断
实体的类型

嗯,这只是F#的一个限制(或特征?)。编译是单遍的,类型干涉自上而下、从左到右进行,没有双回。这使得编译器能够非常快速且非常可预测(看看你,Haskell)


但在这种情况下,这意味着当编译器看到
实体
被用作
缓存中的参数时,它已经决定了它的类型必须是什么。

谢谢。我并没有完全意识到