【问题标题】:Map identity functor over record在记录上映射身份函子
【发布时间】: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 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 来完成它,只是想知道我是否在重新发明轮子。

【问题讨论】:

  • 您也许可以使用 GHC 泛型来做到这一点,但我不知道它是否比 TH 更简单。既然我有 TH 的经验,那也是我的选择。
  • 我会考虑:根本不要使用VehicleState',并为IdentityrunIdentity 设置一个短别名。我知道,不是很好。
  • Identity 是一个新类型,所以cast :: VehicleState Identity -> VehicleState'; cast = unsafeCoerce 在这种情况下实际上是安全的。 (显然反之亦然)
  • 我同意@luqui 的建议;我已经使用它并且效果很好。只需派生镜头以访问VehicleState 的每个字段,然后您可以通过使用镜头组合wrappedunwrapped 来访问Identity 包装的变体。
  • @JohnL,如果你有时间,你能详细说明一下吗?我还不懂镜头。

标签: haskell functor template-haskell


【解决方案1】:

如果您不反对类型族并且不需要太多类型推断,那么您实际上可以使用单一数据类型:

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,这允许您的数据类型的两个版本。但是,您需要 现在为大多数记录键入注释。

【讨论】:

    猜你喜欢
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    相关资源
    最近更新 更多