You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 }

效果说明

  1. 禁止位置参数调用:外部代码无法使用Person "oren" "9200"这种位置参数方式初始化,因为原始构造器MkPerson未导出,而模式同义词Person仅支持记录语法构造。
  2. 仅允许关键字参数:用户必须使用Person { name = "moish", idnum = "7400" }的记录语法来创建Person实例,完全符合需求。
  3. 不影响字段访问:字段访问器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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 21:45:35