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

如何通过Pattern Synonyms抽象Text类型实现,满足指定模式匹配需求?

用模式同义词实现newtype的自定义模式匹配

要实现你想要的效果——让newtype Animal = Animal Text支持Human/NonHuman s的模式匹配,同时区分"human"和其他文本,且解耦实现与匹配语法,可以用GHC的**模式同义词(Pattern Synonyms)**扩展来完成。

模块内部实现(隐藏构造细节)

首先在定义Animal的模块里启用扩展,隐藏原始Animal构造函数,只导出自定义模式和安全的创建函数:

{-# LANGUAGE PatternSynonyms #-}
module Animal
  ( Animal
  , pattern Human
  , pattern NonHuman
  , mkAnimal  -- 安全构造函数,外部只能通过它创建Animal
  ) where

import Data.Text (Text)

newtype Animal = Animal Text

-- 安全构造函数:确保不会生成非法的NonHuman "human"
mkAnimal :: Text -> Animal
mkAnimal "human" = Animal "human"
mkAnimal s = Animal s

-- 定义Human模式:匹配Animal "human"
pattern Human :: Animal
pattern Human = Animal "human"

-- 定义NonHuman模式:仅匹配非"human"的Animal,且外部无法用它构造值
pattern NonHuman :: Text -> Animal
pattern NonHuman s <- Animal s
-- 去掉where子句,让NonHuman只能用于模式匹配,不能在表达式中创建实例

外部使用示例

在其他模块中导入Animal后,就能按你想要的方式模式匹配:

import Animal
import Data.Text (Text)

f :: Animal -> (Bool, Text)
f = \case
  NonHuman s -> (False, s)
  Human -> (True, "human")

关键特性说明

  • 模式匹配逻辑:NonHuman s只会匹配包裹非"human"文本的Animal实例,Human精确匹配Animal "human",完全符合你的需求。
  • 解耦实现与语法:外部不需要知道Animal是基于Text的newtype,只需要使用Human和NonHuman模式即可。
  • 限制非法构造:原始Animal构造函数未导出,外部只能通过mkAnimal创建实例,避免出现NonHuman "human"这种非法值;同时NonHuman没有定义构造行为,外部无法在表达式中使用它创建值。

如果需要在模块内部允许用NonHuman构造合法值,可以给NonHuman加上where子句做合法性检查:

pattern NonHuman :: Text -> Animal
pattern NonHuman s <- Animal s
  where NonHuman s = if s == "human" then error "NonHuman cannot be 'human'" else Animal s

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:03:33