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

如何用newtype实现带提升构造器的递归类型同义词?

解决递归类型同义词的替代方案(Haskell)

首先要明确你混淆了值级别和类型级别的构造器使用:单引号'标记的是DataKinds扩展下的类型级别构造器,而newtype的字段需要的是值级别的类型,这是你代码报错的核心原因。下面分场景给出解决方案:

场景1:定义值级别的递归类型

如果你的需求是创建一个值级别的自引用类型,直接用普通的newtype/data即可,不需要类型级别构造器(单引号):

-- 先定义值级别的基础类型和参数化构造器
data WorldModel a b c = WorldModel a b c
newtype HereParameterised w = HP w

-- 合法的递归newtype,和`newtype Rec = Rec (Maybe Rec)`逻辑一致
newtype PlainWorldModel = PWM (WorldModel Some Instantiation (HereParameterised PlainWorldModel))

这里的Some和Instantiation需要是你预先定义好的具体类型(比如Int、String)。

场景2:定义类型级别的递归类型

如果你的需求是在类型层面定义自引用的WorldModel实例,需要用递归类型族,但要注意递归必须有终止条件(否则类型检查器会因为无限展开报错):

{-# LANGUAGE DataKinds, TypeFamilies #-}

-- 值级别的WorldModel,通过DataKinds提升为类型级别构造器
data WorldModel a b c = WorldModel a b c

-- 定义基础类型和参数化类型族
type Some = Int
type Instantiation = String
type family HereParameterised (w :: WorldModel Type Type Type) :: Type where
  HereParameterised ('WorldModel _ _ c) = c  -- 示例:提取第三个参数作为终止条件

-- 递归类型族定义自引用类型
type family PlainWorldModel :: WorldModel Type Type Type where
  PlainWorldModel = 'WorldModel Some Instantiation (HereParameterised PlainWorldModel)

是否需要singletons库?

  • 如果你只需要值级别的递归:完全不需要。
  • 如果你需要在值级别和类型级别之间建立精确对应(比如要操作一个值,其类型严格匹配类型层面的递归定义):singletons库可以自动生成单例类型和转换函数,避免手动编写大量重复的单例代码。示例:
{-# LANGUAGE TemplateHaskell, DataKinds, TypeFamilies, Singletons #-}
import Data.Singletons.TH

-- 用singletons模板自动生成类型级别和值级别的对应
singletons [d|
  data WorldModel a b c = WorldModel a b c deriving (Show)
  newtype HereParameterised w = HP w deriving (Show)
  |]

-- 类型级别递归定义
type family PlainWorldModel :: WorldModel Type Type Type where
  PlainWorldModel = 'WorldModel 'Int 'String ('HP PlainWorldModel)

-- 值级别单例,对应类型层面的PlainWorldModel
newtype PlainWorldModelVal = PWMV (Sing PlainWorldModel)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:05:20