如何存储Either (Key a) (Key b)?Haskell共享实体多ID存储报错求助
解决Haskell中Sharing实体存储UserId/GroupId的类型作用域问题
你遇到的核心问题是类型不在当前作用域,不管是用Either还是自定义求和类型,本质都是UserId、GroupId或者你自定义的SharingIdType没被Haskell正确识别。我来一步步帮你解决:
1. 先确保基础类型UserId和GroupId已正确定义/导入
报错Not in scope: type constructor or class 'UserId'说明Haskell不知道UserId是什么类型。你需要先明确这个类型的定义:
如果是你自己定义的,要把它放在当前模块或者导入进来:
-- 示例:用newtype定义基础ID类型(也可以用data,根据你的需求调整) newtype UserId = UserId Int newtype GroupId = GroupId Int
如果UserId/GroupId是来自其他模块的,别忘了导入:
import YourModule (UserId, GroupId) -- 替换成实际的模块名
2. 正确定义并使用自定义求和类型SharingIdType
你尝试的自定义求和类型思路是完全正确的,报错Not in scope: type constructor or class 'SharingIdType'大概率是因为这个类型的定义位置不对,或者没被导入到使用它的地方。
正确的写法示例:
-- 先定义基础ID类型(确保它们在当前作用域内) newtype UserId = UserId Int newtype GroupId = GroupId Int -- 定义你的求和类型,明确区分用户ID和群组ID data SharingIdType = SharingUserId UserId | SharingGroupId GroupId -- 现在定义Sharing实体,用SharingIdType来存储对象ID data Sharing = Sharing { sharingObjectId :: SharingIdType -- 这里可以添加其他字段,比如sharingPermission、sharingCreatedAt等 }
如果SharingIdType在另一个模块:
- 在定义它的模块里要导出这个类型(包括构造函数,方便后续模式匹配):
module YourDataModule ( UserId(..) , GroupId(..) , SharingIdType(..) , Sharing(..) ) where -- 然后是类型定义... - 在使用
Sharing的模块里导入:import YourDataModule (SharingIdType(..), Sharing(..))
3. (可选)如果想用Either代替自定义类型
如果你觉得自定义类型麻烦,想用Either,只要确保UserId和GroupId在作用域,直接用就行:
data Sharing = Sharing { sharingObjectId :: Either UserId GroupId -- 其他字段... }
不过我更推荐自定义求和类型,因为Left/Right的语义不如SharingUserId/SharingGroupId清晰,后续模式匹配时可读性会高很多。
错误原因总结
所有Not in scope的类型错误,本质都是Haskell在当前代码的作用域里找不到对应的类型定义:
- 要么是你没定义这个类型;
- 要么是定义了但没导入到当前模块;
- 要么是定义在局部作用域(比如某个函数内部),外部无法访问。
内容的提问来源于stack exchange,提问作者arrowd
相关产品推荐
相关产品推荐

