Haskell Esqueleto如何直接将列子集映射至自定义记录而非元组?
当然可以直接投影到自定义记录!
Esqueleto完全支持将查询结果直接投影到你自己定义的非实体记录类型,不需要先转成元组再手动转换——这样代码更清晰,还能利用类型系统保证字段匹配。
具体实现步骤:
先定义你的自定义记录类型
比如针对你的日志项场景,我们可以定义一个只包含需要字段的记录:data LogItemSummary = LogItemSummary { summaryId :: Int64 -- 对应LogItemId的类型 , summaryTitle :: Text -- 对应LogItemTitle的类型 } deriving (Show, Eq)在查询中直接构造自定义记录返回
在Esqueleto的查询块里,你可以用Applicative语法(<$>和<*>)把查询到的列值直接传给自定义记录的构造函数:previousLogItems <- select $ from $ \li -> do orderBy [desc (li ^. LogItemId)] limit 10 -- 直接构造LogItemSummary的SqlExpr版本 return $ LogItemSummary <$> li ^. LogItemId <*> li ^. LogItemTitle如果你习惯用record语法,也可以这样写(本质和上面是一样的):
return $ (\itemId itemTitle -> LogItemSummary { summaryId = itemId , summaryTitle = itemTitle }) <$> li ^. LogItemId <*> li ^. LogItemTitle
为什么这样可行?
Esqueleto的SqlExpr是一个Applicative functor,所以我们可以用<$>和<*>把普通的记录构造函数“提升”到SqlExpr上下文里,让它能接收查询返回的列表达式(SqlExpr a类型的值),最终返回一个SqlExpr LogItemSummary——而select函数会自动把这个表达式转换成实际的LogItemSummary列表返回给你。
这种方式不仅省去了元组转换的麻烦,还能让编译器帮你检查字段类型是否匹配,避免手动转换时可能出现的错误。
内容的提问来源于stack exchange,提问作者Răzvan Flavius Panda
相关产品推荐
相关产品推荐

