我对 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

1.) 这是可接受的解决方案吗?
2.) 对于我的教育:有没有办法避免“
-- Doesn't compile - need to enter with the map into the m***d - how ?
getAllTickers'' = map unValue (select $ from $ \i -> return (i ^. InstrumentTicker))

最佳答案

我对 esqueleto 没有任何经验,但在快速浏览教程后,我认为这应该可行:

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

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

编辑:

我在您的解决方案中没有发现 unValue 有任何问题,但请不要在这方面引用我。如果你想避免 do-notation,一种方法是你可以利用 Monad 也是 Functor 的事实,所以你可以使用中缀 <$> 也称为 fmap :
getAllTickers' :: (MonadIO m, MonadLogger m) => SqlReadT m [String]
getAllTickers' =
  map unValue <$> (select $ from $ \i -> return (i ^. InstrumentTicker))

关于database - Esqueleto 只返回一列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58569635/

10-12 14:01