Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 记录上的映射恒等函子_Haskell_Functor_Template Haskell - Fatal编程技术网

Haskell 记录上的映射恒等函子

Haskell 记录上的映射恒等函子,haskell,functor,template-haskell,Haskell,Functor,Template Haskell,我有一个这样的记录类型: data VehicleState f = VehicleState { orientation :: f (Quaternion Double), orientationRate :: f (Quaternion Double), acceleration :: f (V3 (Acc

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

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信号
其中我有各种元数据,我可以有一个
VehicleState(Wire s e m())
其中我有每个信号的
netwire
语义,或者我可以有一个
VehicleState标识
,其中我有在特定时间观察到的实际值

是否有一种在
车辆状态标识
车辆状态
之间来回映射的好方法,通过映射每个字段上的
运行标识
来定义

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模板来实现这一点,只是想知道我是否在重新发明轮子。

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

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
类型族。它可以应用于 该包中还定义了各种类型的函数(当然,您可以定义 自己的)。
IdSym0
的属性是
Apply IdSym0 x
减少为普通的
x
。及
TyCon1
具有
Apply(tycon1f)x
减少为
fx
的属性

正如
test1
test2
,这允许您的数据类型的两个版本。然而,你需要
现在为大多数记录键入注释。

您可能可以使用GHC泛型实现这一点,但我不知道它是否比TH更简单。既然我有TH的经验,那也是我的选择。我要考虑的是:根本不要使用
VehicleState'
,为
Identity
runIdentity
做一个简短的别名。我知道,不太好。
Identity
是一种新类型,所以
cast::VehicleState Identity->VehicleState';在这种情况下,cast=unsafeccerce
实际上是安全的。(显然,反过来也是一样)我同意@luqui的建议;我用过它,效果很好。只需导出透镜以访问
车辆状态的每个字段
,然后您就可以通过使用透镜组合
包装的
展开的
来访问
身份包装的变体。@JohnL,如果您有时间,您能详细说明一下吗?我还不懂镜头。