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

如何使用Template Haskell生成带辅助构造函数的newtype包装器

实现代码

首先需要开启TemplateHaskell扩展并导入相关依赖:

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Data.Char (toLower)

type UID = Integer

wrapUID :: String -> Q [Dec]
wrapUID n = do
  -- 生成原有的newtype类型声明
  newtypeDec <- dataD (cxt []) 
                      typeName
                      []
                      Nothing
                      [normalC typeName 
                        [bangType (bang noSourceUnpackedness noSourceStrictness)
                        [t| UID |]]]
                      []
  -- 生成辅助构造函数的类型签名
  funSig <- sigD funName [t| forall a. Integral a => a -> $(conT typeName) |]
  -- 生成辅助构造函数的实现逻辑
  funImpl <- funD funName
    [ clause []
      (normalB [| $(conE typeName) . fromInteger |])
      []
    ]
  return [newtypeDec, funSig, funImpl]
  where
    typeName = mkName n
    -- 自动将类型名首字母转小写,生成对应的构造函数名
    funName = mkName $ case n of
      (c:cs) -> toLower c : cs
      [] -> error "wrapUID: 传入的类型名称不能为空"
用法说明

在需要生成ID包装类型的模块直接调用TH函数即可:

-- 调用后会自动生成两组代码:
-- 1. newtype MyRecordID = MyRecordID UID
-- 2. myRecordID :: Integral a => a -> MyRecordID
--    myRecordID = MyRecordID . fromInteger
$(wrapUID "MyRecordID")
  • 注意:传入wrapUID的字符串必须为大驼峰格式的类型名,函数会自动转换首字母大小写生成符合命名规范的辅助构造函数。
  • 生成的辅助构造函数可直接接收任意Integral类型入参,包括数据库返回的Int32类型,无需额外手动做类型转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 17:36:03