Haskell中如何强制初始化记录类型时仅使用关键字参数?
实现仅允许关键字参数初始化Haskell记录类型
要禁止通过位置参数初始化Person类型,仅允许记录语法(关键字参数),可以通过隐藏原始构造器+模式同义词的方式实现,具体步骤如下:
方案代码
{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RecordPatternSynonyms #-} -- 模块导出列表:仅导出Person类型、模式同义词Person,以及字段访问器 module Person ( Person , pattern Person , name , idnum ) where -- 原始数据类型,构造器MkPerson设为私有(不对外导出) data Person = MkPerson { name :: String , idnum :: String } deriving (Show) -- 定义仅支持记录语法的模式同义词 pattern Person { name, idnum } :: Person pattern Person { name, idnum } <- MkPerson { name, idnum } where Person { name, idnum } = MkPerson { name, idnum }
效果说明
- 禁止位置参数调用:外部代码无法使用
Person "oren" "9200"这种位置参数方式初始化,因为原始构造器MkPerson未导出,而模式同义词Person仅支持记录语法构造。 - 仅允许关键字参数:用户必须使用
Person { name = "moish", idnum = "7400" }的记录语法来创建Person实例,完全符合需求。 - 不影响字段访问:字段访问器
name和idnum正常导出,依然可以通过personName = name somePerson的方式访问字段值。
替代方案(无需扩展)
如果不想使用GHC扩展,也可以通过智能构造函数+私有配置记录实现:
module Person ( Person , name , idnum , createPerson ) where data Person = Person { name :: String , idnum :: String } deriving (Show) -- 私有配置记录(构造器不导出) data PersonConfig = PersonConfig { cfgName :: String , cfgIdnum :: String } -- 智能构造函数,仅接受配置记录 createPerson :: PersonConfig -> Person createPerson cfg = Person { name = cfgName cfg , idnum = cfgIdnum cfg }
用户必须通过createPerson PersonConfig{ cfgName = "moish", cfgIdnum = "7400" }创建实例,同样避免了位置参数的误用。
内容的提问来源于stack exchange,提问作者OrenIshShalom
相关产品推荐
相关产品推荐

