在记录上映射身份仿函数

时间:2014-07-23 22:51:01

标签: haskell functor template-haskell

我有一个像这样的记录类型:

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 IdentityVehicleState'之间来回映射的好方法,通过在每个字段上映射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,只是想知道我是否正在重新发明轮子。

1 个答案:

答案 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的属性。

如所示 test1test2,这允许您的数据类型的两个版本。但是,你需要 现在为大多数记录输入注释。