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

如何自动生成PureScript枚举全值数组并确保其完整性?

PureScript枚举类型全值数组的生成与校验方案

先看你定义的代码:

data Icon = IconCircle | IconSquare | IconStar

还有对应的全值数组:

allPossible :: Array Icon
allPossible = [IconCircle, IconSquare, IconStar]

一、快捷生成全值数组的办法

PureScript本身没有自动生成枚举全值的原生语法,但可以用类型类来简化维护:

  1. 先定义一个Enumerable类型类,专门用来获取某个类型的所有取值:
class Enumerable a where
  allValues :: Array a
  1. 给Icon实现这个类型类:
instance enumerableIcon :: Enumerable Icon where
  allValues = [IconCircle, IconSquare, IconStar]

第一次还是要手动列全,但后续如果新增Icon的取值,只需要修改这个实例里的数组就行,不用到处找引用,逻辑更集中。

另外社区里有purescript-enums这类库,提供了现成的枚举处理工具,能进一步简化全值生成的代码。

二、用类型系统强制数组不遗漏取值

如果想从类型层面确保数组包含所有Icon取值,可以借助PureScript的类型级编程能力:

方案:类型级长度校验

核心思路是让编译器检查数组的长度和Icon构造器的数量完全一致——只要新增构造器但没更新数组,编译直接报错。

  1. 先把Icon的构造器映射到类型行,再定义计算类型行长度的类型家族:
-- 用类型行列出所有Icon构造器
type IconConstructors = (circle :: Unit, square :: Unit, star :: Unit)

-- 类型级函数:计算类型行的长度
type family RowLength (r :: # Type) :: Nat
type instance RowLength () = 0
type instance RowLength (l :: a | r) = 1 + RowLength r

-- 定义带长度约束的数组类型
type ExactLengthArray (n :: Nat) a = { length :: n, content :: Array a }

-- 辅助函数:编译期检查数组长度是否匹配
mkExactLengthArray :: forall n a. SNat n -> Array a -> Maybe (ExactLengthArray n a)
mkExactLengthArray n arr = if length arr == reflectNat n
  then Just { length: n, content: arr }
  else Nothing
  1. 用这个约束定义allPossible:
allPossible :: ExactLengthArray (RowLength IconConstructors) Icon
allPossible = case mkExactLengthArray (snat :: SNat (RowLength IconConstructors)) [IconCircle, IconSquare, IconStar] of
  Just arr -> arr.content
  Nothing -> error "allPossible数组长度和Icon构造器数量不匹配"

这样以后只要给Icon加新的构造器,比如IconTriangle,就得同步更新IconConstructors类型行和allPossible数组,否则编译通不过,从根源避免遗漏。

总结

  • 快捷维护:用Enumerable类型类把全值数组集中管理,或者用社区枚举库减少重复代码。
  • 类型安全:通过类型级长度校验,让编译器帮你把关数组是否包含所有枚举取值,不用手动检查。

内容的提问来源于stack exchange,提问作者christian wuensche

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:40:49