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