【发布时间】:2014-07-23 22:51:01
【问题描述】:
我有这样一个记录类型:
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 来完成它,只是想知道我是否在重新发明轮子。
【问题讨论】:
-
您也许可以使用 GHC 泛型来做到这一点,但我不知道它是否比 TH 更简单。既然我有 TH 的经验,那也是我的选择。
-
我会考虑:根本不要使用
VehicleState',并为Identity和runIdentity设置一个短别名。我知道,不是很好。 -
Identity是一个新类型,所以cast :: VehicleState Identity -> VehicleState'; cast = unsafeCoerce在这种情况下实际上是安全的。 (显然反之亦然) -
我同意@luqui 的建议;我已经使用它并且效果很好。只需派生镜头以访问
VehicleState的每个字段,然后您可以通过使用镜头组合wrapped或unwrapped来访问Identity包装的变体。 -
@JohnL,如果你有时间,你能详细说明一下吗?我还不懂镜头。
标签: haskell functor template-haskell