Haskell 将类型构造函数应用于记录类型的组件
给定一个固定类型构造函数T和一个记录类型R,是否有一种机制来为其组件为R的组件但T应用于该类型的记录类型创建声明 例如,T是Haskell 将类型构造函数应用于记录类型的组件,haskell,template-haskell,Haskell,Template Haskell,给定一个固定类型构造函数T和一个记录类型R,是否有一种机制来为其组件为R的组件但T应用于该类型的记录类型创建声明 例如,T是可能是,而R data Foo { bar :: Int, baz :: Bool } 机制应该给予, data Foo { bar :: Maybe Int, baz :: Maybe Bool } 或者可能 data FooOpt { barOpt :: Maybe Int, bazOpt :: Maybe Bool } 其中,Opt后缀指
可能是,而R
data Foo {
bar :: Int,
baz :: Bool
}
机制应该给予,
data Foo {
bar :: Maybe Int,
baz :: Maybe Bool
}
或者可能
data FooOpt {
barOpt :: Maybe Int,
bazOpt :: Maybe Bool
}
其中,Opt
后缀指定为参数。您可以使用另一个类型(通常是函子)参数化您的类型,并执行以下操作
他们使用Foo身份
和Foo可能
。这方面的问题是Foo Identity
不会给您{bar::Int,baz::Bool}
,而是{bar::Identity Int,baz::Identity Bool}
。它在语义上是等价的,但在实践中是一种痛苦,因为您必须从标识中展开所有字段
然而,其优点是,您可以编写在f
上通用的方法,并同时适用于Foo-Identity
和Foo-Maybe
。您可以通过使用类型族来摆脱标识
type family EraseIdentity f a where
EraseIdentity Identity a = a
EraseIdentity f a = f a
data Foo f = Foo {
bar :: EraseIdentity f Int
baz :: EraseIdentity f Bool
}
类型族是类型上的函数,您在这里要说的是,将Identity a
转换为a
。现在Foo-Identity
是一个{bar::Int,baz::Bool}
你能用像数据Foo-f{bar::Int,baz::f-Bool}
这样简单的方法来解决这个问题吗?或者你需要单独类型的类型安全性吗?不,我不能接触原始类型。你确定不能概括原始类型,所以按照Alexis的建议使用近似同构的类型吗?否则,我想模板Haskell是你唯一的选择,但我想知道你为什么真的需要它。你真的需要一个合适的数据
声明(在这种情况下,没有办法绕过TH),还是只需要一些与修改后的R
同构的类型?在这种情况下,仅使用泛型的解决方案是可能的(这当然需要R
的Generic
实例,但这不应该是一个障碍)。我不知道你的身份
type family EraseIdentity f a where
EraseIdentity Identity a = a
EraseIdentity f a = f a
data Foo f = Foo {
bar :: EraseIdentity f Int
baz :: EraseIdentity f Bool
}