用GHC.Generics提取id

时间:2017-11-23 10:48:51

标签: haskell generic-programming ghc-generics

如何使用GHC.Generics

从结构中提取标识符(在本例中为整数)

我有一个Id类型:

newtype Id = Id { _id :: Int }

以及许多使用该类型的类型:

data VarId = VarId Name Id SortId
data FuncId = FuncId Name Id [SortId] SortId
data SortId = Name Id
-- ... and 20 more of these things

除此之外,还有其他类型包装上面的类型,例如,标识符:

data Identifier = IdVar VarId
                | IdFunc FuncId
                | IdSort SortId
                -- ... and 20 more of these things

现在我需要从包含_id值的任何类型中提取Id字段。目前我们有大量的样板,我想用泛型废弃它。

起初我想过定义一个类:

class Identifiable e where
    getId :: e -> Id

    default getId :: (Generic e, GIdentifiable (Rep e)) => e -> Id
    getId = gGetId . from

class GIdentifiable f where
    gGetId :: f e -> Id

如果内部有一个Identifiable类型,那么您只有Id个实例 (如果有多个类似于上面FuncId我们返回从顶部到底部遍历结构时找到的第一个Id。现在,当我尝试为产品和总和定义GIdentifiable实例时出现问题。我想表达的意思是:

instance (GIdentifiable a) => GIdentifiable (a :*: b) where
    gGetId (a :*: _) = gGetId a

instance {-# OVERLAPS #-} (GIdentifiable b) => GIdentifiable (a :*: b) where
gGetId (_ :*: b) = gGetId b

哪个不起作用,因为我正在定义重复的实例。

我可以重新定义Identifiable以便getId :: e -> Maybe Id,但这会删除某些类型的安全性,并在我知道类型包含至少一个{{strong>时 - 引入不必要的检查{1}}。

使用类型系统时,有没有办法表达这种案例分析?

0 个答案:

没有答案