You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell Esqueleto如何直接将列子集映射至自定义记录而非元组?

当然可以直接投影到自定义记录!

Esqueleto完全支持将查询结果直接投影到你自己定义的非实体记录类型,不需要先转成元组再手动转换——这样代码更清晰,还能利用类型系统保证字段匹配。

具体实现步骤:

  1. 先定义你的自定义记录类型
    比如针对你的日志项场景,我们可以定义一个只包含需要字段的记录:

    data LogItemSummary = LogItemSummary
      { summaryId    :: Int64  -- 对应LogItemId的类型
      , summaryTitle :: Text   -- 对应LogItemTitle的类型
      } deriving (Show, Eq)
    
  2. 在查询中直接构造自定义记录返回
    在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:30:01