我有一个像这样的记录类型:
data VehicleState f = VehicleState
{
orientation :: f (Quaternion Double),
orientationRate :: f (Quaternion Double),
acceleration :: f (V3 (Acceleration Double)),
velocity :: f (V3 (Velocity Double)),
location :: f (Coordinate),
elapsedTime :: f (Time Double)
}
deriving (Show)
这很酷,因为我可以有一个VehicleState Signal
我有各种各样的元数据,我可以有一个VehicleState (Wire s e m ())
,其中我有每个信号的netwire
语义,或者我可以有VehicleState Identity
我在某个时间观察到的实际值。
是否有一种在VehicleState Identity
和VehicleState'
之间来回映射的好方法,通过在每个字段上映射runIdentity
来定义?
data VehicleState' = VehicleState'
{
orientation :: Quaternion Double,
orientationRate :: Quaternion Double,
acceleration :: V3 (Acceleration Double),
velocity :: V3 (Velocity Double),
location :: Coordinate,
elapsedTime :: Time Double
}
deriving (Show)
显然写一个是微不足道的,但实际应用中我实际上有几种这样的类型,我不断添加或删除字段,所以这很乏味。
我正在编写一些模板Haskell,只是想知道我是否正在重新发明轮子。
答案 0 :(得分:3)
如果您不反对打字系列并且不需要太多的类型推断,那么您实际上可以使用单一数据类型:
import Data.Singletons.Prelude
data Record f = Record
{ x :: Apply f Int
, y :: Apply f Bool
, z :: Apply f String
}
type Record' = Record IdSym0
test1 :: Record (TyCon1 Maybe)
test1 = Record (Just 3) Nothing (Just "foo")
test2 :: Record'
test2 = Record 2 False "bar"
Apply
类型系列在singletons包中定义。它可以应用于
各种类型的功能也在该包中定义(当然,你可以定义你的
拥有)。 IdSym0
具有Apply IdSym0 x
缩减为普通x
的属性。和
TyCon1
具有Apply (TyCon1 f) x
缩减为f x
的属性。
如所示
test1
和test2
,这允许您的数据类型的两个版本。但是,你需要
现在为大多数记录输入注释。