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

Haskell中混合类型模式匹配与记录语法的编译问题

GADT匹配:类型应用与记录语法结合的解决方案

问题场景

我们定义了带记录字段的GADT及相关函数:

data T where
  T :: (Typeable a, Integral a) => { first :: a, second :: a } -> T

printType :: forall a. Typeable a => String
printType = show $ typeRep (Proxy :: Proxy a)

f :: T -> String
f (T first second) = show (toInteger first, toInteger second)

单独使用记录语法匹配字段是可行的:

f (T {first, second}) = show (toInteger first, toInteger second)

单独使用类型应用获取GADT的类型参数也没问题:

f (T @a first second) = printType @a ++ ": " ++ show (toInteger first, toInteger second)

但尝试将两者结合时,f (T @a {first, second})会编译失败——GHC目前不支持这种语法组合。

可行的替代方案

1. As模式+记录访问器

直接用As模式绑定整个值,匹配类型参数后通过记录访问器提取字段,无需额外语法扩展:

f t@(T @a _ _) = printType @a ++ ": " ++ show (toInteger (first t), toInteger (second t))

2. As模式+局部记录模式匹配

如果觉得访问器写法不够直观,可以用局部绑定提取记录字段,开启扩展后还能进一步简化:

f t@(T @a _ _) = let T{first, second} = t
                  in printType @a ++ ": " ++ show (toInteger first, toInteger second)

开启RecordWildCards扩展后,写法更简洁:

{-# LANGUAGE RecordWildCards #-}

f t@(T @a _ _) = let T{..} = t
                  in printType @a ++ ": " ++ show (toInteger first, toInteger second)

3. 视图模式(需开启ViewPatterns)

借助视图模式可以把类型匹配和字段提取整合到模式中,不过需要额外开启扩展:

{-# LANGUAGE ViewPatterns #-}

f (T @a -> T {first, second}) = printType @a ++ ": " ++ show (toInteger first, toInteger second)

总结

截至GHC 9.6版本,官方语法仍不支持直接将类型应用与记录模式结合,但上述几种方案都能简洁实现需求,其中As模式+记录访问器是最轻量化的选择,无需任何额外扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:24:53