Haskell 如何获得具有过载字段名称的经典镜头?
我正在尝试为具有相同字段名的记录构建镜头。除此之外,我正在尝试“包装/扩展”这些基本记录,并希望相同的字段名适用于包装/扩展的记录(我相信,经典镜头可以做到这一点)。如何使以下各项发挥作用:Haskell 如何获得具有过载字段名称的经典镜头?,haskell,haskell-lens,lenses,Haskell,Haskell Lens,Lenses,我正在尝试为具有相同字段名的记录构建镜头。除此之外,我正在尝试“包装/扩展”这些基本记录,并希望相同的字段名适用于包装/扩展的记录(我相信,经典镜头可以做到这一点)。如何使以下各项发挥作用: -- Data types for context of the code snippet below data Download = Download { userId :: UserId ,gid :: Gid ,logId :: LogId ,parentId :: Maybe Do
-- Data types for context of the code snippet below
data Download = Download {
userId :: UserId
,gid :: Gid
,logId :: LogId
,parentId :: Maybe DownloadId
,createdAt :: UTCTime
,updatedAt :: UTCTime
}
data File = File {
downloadId :: DownloadId
,fpath :: String
,len :: Int
,createdAt :: UTCTime
,updatedAt :: UTCTime
}
data Url = Url {
downloadId :: DownloadId
,fileId :: FileId
,url :: URL
,createdAt :: UTCTime
,updatedAt :: UTCTime
}
data DownloadObject = DownloadObject {
_key :: DownloadId
,_dbDownload :: Download
,_dbFiles :: [FileObjects]
}
data FileObject = FileObject {
_key :: FileId
,_dbFile :: File,
,_dbUrls :: [UrlObjects]
}
data UrlObject = UrlObject {
_key :: UrlId
,_dbUrl :: Url
}
fetchDownload :: DownloadId -> DownloadObject
鉴于这些数据类型,我如何使以下镜头工作:
dload <- fetchDownload dloadId
dload ^. key -- of type DownloadId
dload ^. createdAt -- of type UTCTime
((dload ^. files) !! 1) ^. key -- of type FileId
((dload ^. files) !! 1) ^. createdAt -- of type UTCTime
dload使用makeFields
from:
现在您有了以下类:
class HasName s a | s -> a where
name :: Lens' s a
class HasAge s a | s -> a where
age :: Lens' s a
以及Foo
和Bar
的相应实例。例如:
> Foo 10 "foo" ^. age
10
> Bar 10 "bar" ^. age
10
data FooWrapper = FooWrapper {
_fooWrapperKey :: Int,
_fooWrapperFoo :: Foo
} deriving Show
makeFields ''FooWrapper
instance HasName FooWrapper String where
name = foo . name
instance HasAge FooWrapper Int where
age = foo . age
然后可以实现包装器对象的类。例如:
> Foo 10 "foo" ^. age
10
> Bar 10 "bar" ^. age
10
data FooWrapper = FooWrapper {
_fooWrapperKey :: Int,
_fooWrapperFoo :: Foo
} deriving Show
makeFields ''FooWrapper
instance HasName FooWrapper String where
name = foo . name
instance HasAge FooWrapper Int where
age = foo . age
谢谢你的回复。我认为你错过了问题的关键部分。我想让镜头处理包装/扩展的记录,即下载对象
,文件对象
,和UrlObject
,而不是下载
,文件
,以及Url
,有没有其他方法可以在不必自己编写所有镜头相关的模板的情况下编写这些记录(HasName
HasAge
等实例)?一个糟糕的答案:你可以使用模板Haskell来自动化大部分内容。它的API和文档很复杂,但它是可行的。据我所知,lens库没有提供这样做的方法。啊……我多么怀念Ruby元编程和Lisp宏!