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

如何手动定义GHC.Generic实例?类型检查错误排查

手动实现GHC.Generic实例的问题排查与解决

GHC通常会通过deriving机制自动为数据类型生成GHC.Generic类的实例,但该机制对带隐式参数的行类型和匿名记录无效。因此尝试手动定义Generic实例,先以常规数据类型Point做实验:

通过GHCi获取Generic表示

在GHCi中执行以下命令,获取Point的Generic结构:

> import GHC.Generics
> data Point = Point { x :: Int, y :: Int } deriving (Show, Eq, Generic)
> from (Point 1 2)
M1 {unM1 = M1 {unM1 = M1 {unM1 = K1 {unK1 = 1}} :*: M1 {unM1 = K1 {unK1 = 2}}}}
> :i Rep Point
type instance Rep Point
  = D1
      (MetaData
         "Point"
         "RowTypeDemo.ImplicitParamsAsAlternativeToRowType"
         "row-type-demo-0.0.1-inplace"
         False)
      (C1
         (MetaCons "Point" PrefixI True)
         (S1
            (MetaSel
               (Just "x") NoSourceUnpackedness NoSourceStrictness DecidedLazy)
            (Rec0 Int)
          :*: S1
                (MetaSel
                   (Just "y") NoSourceUnpackedness NoSourceStrictness DecidedLazy)
                (Rec0 Int)))

手动实现Generic实例并报错

复制上述表示手动实现Generic实例:

data Point = Point { x :: Int, y :: Int } deriving (Show, Eq)
instance Generic Point where
  type Rep Point =
    D1
      (MetaData
         "Point"
         "RowTypeDemo.ImplicitParamsAsAlternativeToRowType"
         "row-type-demo-0.0.1-inplace"
         False)
      (C1
         (MetaCons "Point" PrefixI True)
         (S1
            (MetaSel
               (Just "x") NoSourceUnpackedness NoSourceStrictness DecidedLazy)
            (Rec0 Int)
          :*: S1
                (MetaSel
                   (Just "y") NoSourceUnpackedness NoSourceStrictness DecidedLazy)
                (Rec0 Int)))
  from :: Point -> Rep Point x
  from r = M1 {unM1 = L1 (M1 {unM1 = M1 {unM1 = K1 {unK1 = x r}} :*: M1 {unM1 = K1 {unK1 = y r}}})}

类型检查器报错如下:

• Couldn't match type: M1
                         i0 c0 (M1 i1 c1 (K1 i2 Int) :*: M1 i3 c2 (K1 i4 Int))
                       :+: g0
                 with: M1
                         C
                         (MetaCons "Point" PrefixI True)
                         (S1
                            (MetaSel
                               (Just "x") NoSourceUnpackedness NoSourceStrictness DecidedLazy)
                            (Rec0 Int)
                          :*: S1
                                (MetaSel
                                   (Just "y")
                                   NoSourceUnpackedness
                                   NoSourceStrictness
                                   DecidedLazy)
                                (Rec0 Int))
  Expected: Rep Point x
    Actual: M1
              D
              (MetaData
                 "Point"
                 "RowTypeDemo.ImplicitParamsAsAlternativeToRowType"
                 "row-type-demo-0.0.1-inplace"
                 False)
              (M1 i0 c0 (M1 i1 c1 (K1 i2 Int) :*: M1 i3 c2 (K1 i4 Int)) :+: g0)
              x
• In the expression:
    M1
      {unM1 = L1
                (M1
                   {unM1 = M1 {unM1 = K1 {unK1 = x r}}
                             :*: M1 {unM1 = K1 {unK1 = y r}}})}
  In an equation for ‘from’:
      from r
        = M1
            {unM1 = L1
                      (M1
                         {unM1 = M1 {unM1 = K1 {unK1 = x r}}
                                   :*: M1 {unM1 = K1 {unK1 = y r}}})}
  In the instance declaration for ‘Generic Point’    | 87 |   from r = M1 {unM1 = L1 (M1 {unM1 = M1 {unM1 = K1 {unK1 = x r}} :*: M1 {unM1

= K1 {unK1 = y r}}})} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

使用GHC版本为9.8.1,启用的扩展包括DataKinds、LambdaCase等。

问题修正

最初误以为GHCi生成的表示有误,后来发现是误用了和类型表示的L1,修正后的实现通过类型检查:

from :: Point -> Rep Point x
  from r = M1 {unM1 = (M1 {unM1 = M1 {unM1 = K1 {unK1 = x r}} :*: M1 {unM1 = K1 {unK1 = y r}}})}

  to (M1 {unM1 = (M1 {unM1 = M1 {unM1 = K1 {unK1 = xx}} :*: M1 {unM1 = K1 {unK1 = yy}}})}) = Point xx yy

确认错误原因:误用了和类型表示的L1构造函数,而Point是单构造函数类型,不需要用L1包裹构造器的Generic表示。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:04:51