Reputation: 2238
I'm quite new to Haskell, currently doing my best to prevent my brain from going inside out. I've got a very simple DB schema defined in that way:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Instrument
ticker String
source String
exchange String
deriving Eq Show
|]
I noticed that I can query for the all entries in the table in the following way:
getAllInstruments :: (MonadIO m, MonadLogger m) => SqlReadT m [Entity Instrument]
getAllInstruments = select $ from $ \instrument -> do return instrument
However, what if I'd like to get just a single column ? I tried something like this:
-- doesn't compile
getAllTickers :: (MonadIO m, MonadLogger m) => SqlReadT m [String]
getAllTickers = select $ from $ \instrument -> do return (Value (instrument ^. ticker))
But I get an error message:
• Couldn't match expected type ‘EntityField val0 typ0’
with actual type ‘StockPrice -> Ticker’
I found a similar question on how to return a subset of columns here: Haskell Esqueleto project subset of columns to list of custom records
And my question is: do I need to implement all the types like described in the article I posted in my application as well (i.e. only for a single column/field) ?
EDIT
Thanks to the hint I managed to come up with the following piece of code:
getAllTickers' :: (MonadIO m, MonadLogger m) => SqlReadT m [String]
getAllTickers' = do
res <- select $ from $ \i -> return (i ^. InstrumentTicker)
return $ map unValue res
1.) Is it acceptable solution ? 2.) For my education: is there a way to avoid the "<-" notation ? Specifically I wonder if there's a way to write it in the following way:
-- Doesn't compile - need to enter with the map into the m***d - how ?
getAllTickers'' = map unValue (select $ from $ \i -> return (i ^. InstrumentTicker))
Upvotes: 3
Views: 307
Reputation: 31
For your last question, try:
getAllTickers'' = map unValue <$> (select $ from $ \i -> return (i ^. InstrumentTicker))
Upvotes: 0
Reputation: 861
I do not have any experience with esqueleto, but after a quick look at the tutorials I think this should work:
getAllTickers :: (MonadIO m, MonadLogger m) => SqlReadT m [Value String]
getAllTickers = select $ from $ \instrument -> return (instrument ^. InstrumentTicker)
note different type in signature and different lens. Hope it helps.
EDIT:
I don't see anything wrong with unValue
in your solution, but don't cite me on that. If you want to avoid do-notation, one of the ways is you can exploit the fact that a Monad is also a Functor, so you can use infix <$>
also known as fmap
:
getAllTickers' :: (MonadIO m, MonadLogger m) => SqlReadT m [String]
getAllTickers' =
map unValue <$> (select $ from $ \i -> return (i ^. InstrumentTicker))
Upvotes: 1