代码之家  ›  专栏  ›  技术社区  ›  LA.27

Esqueleto只返回一列

  •  0
  • LA.27  · 技术社区  · 6 年前

    我对Haskell还是个新手,目前正在尽我最大的努力防止我的大脑从内到外。 我用这种方式定义了一个非常简单的数据库模式:

    share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
      Instrument
        ticker String
        source String
        exchange String
        deriving Eq Show
    |]
    

    我注意到我可以通过以下方式查询表中的所有条目:

    getAllInstruments :: (MonadIO m, MonadLogger m) => SqlReadT m [Entity Instrument]
    getAllInstruments = select $ from $ \instrument -> do return instrument
    

    但是,如果我只想得到一个专栏呢?我试过这样的方法:

    -- doesn't compile
    getAllTickers :: (MonadIO m, MonadLogger m) => SqlReadT m [String]
    getAllTickers = select $ from $ \instrument -> do return (Value (instrument ^. ticker))
    

    • Couldn't match expected type ‘EntityField val0 typ0’
      with actual type ‘StockPrice -> Ticker’
    

    关于如何返回列的子集,我发现了一个类似的问题: Haskell Esqueleto project subset of columns to list of custom records

    多亏了这个提示,我终于想出了以下代码:

    getAllTickers' :: (MonadIO m, MonadLogger m) => SqlReadT m [String]
    getAllTickers' = do 
      res <- select $ from $ \i -> return (i ^. InstrumentTicker)
      return $ map unValue res
    

    -- Doesn't compile - need to enter with the map into the m***d - how ?
    getAllTickers'' = map unValue (select $ from $ \i -> return (i ^. InstrumentTicker))
    
    0 回复  |  直到 6 年前
        1
  •  1
  •   DevNewb    6 年前

    我没有使用esqueleto的任何经验,但是在快速浏览了教程之后,我认为这应该会起作用:

    getAllTickers :: (MonadIO m, MonadLogger m) => SqlReadT m [Value String]
    getAllTickers = select $ from $ \instrument -> return (instrument ^. InstrumentTicker)
    

    注意不同类型的签名和不同的镜头。希望有帮助。

    我看不出有什么问题 unValue 在你的解决方案中,但不要引用我的话。如果你想避免用do表示法,方法之一就是利用Monad也是函子这一事实,这样就可以使用中缀 <$> fmap

    getAllTickers' :: (MonadIO m, MonadLogger m) => SqlReadT m [String]
    getAllTickers' = 
      map unValue <$> (select $ from $ \i -> return (i ^. InstrumentTicker))