我对 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 的事实,所以你可以使用 infix <$>
也称为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/