Esqueleto вернуть только один столбец - PullRequest
3 голосов
/ 26 октября 2019

Я довольно новичок в Хаскеле, в настоящее время делаю все возможное, чтобы мой мозг не вылетел наизнанку. У меня очень простая схема БД, определенная таким образом:

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’

Я нашел похожий вопрос о том, как вернуть подмножество столбцов здесь: HaskellEsqueleto проект подмножество столбцов в список пользовательских записей

И мой вопрос: мне нужно реализовать все типы, как описано в статье, которую я также опубликовал в своем приложении (т.е. только для одногостолбец / поле)?

РЕДАКТИРОВАТЬ

Благодаря подсказке мне удалось придумать следующий фрагмент кода:

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

1.) Является ли это приемлемым решением? ? 2.) Для моего образования: есть ли способ избежать обозначения <-? В частности, мне интересно, есть ли способ написать это следующим образом: </p>

-- Doesn't compile - need to enter with the map into the m***d - how ?
getAllTickers'' = map unValue (select $ from $ \i -> return (i ^. InstrumentTicker))

1 Ответ

1 голос
/ 28 октября 2019

У меня нет опыта работы с esqueleto, но после быстрого просмотра учебников я думаю, что это должно сработать:

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

обратите внимание на другой тип подписи и другой объектив. Надеюсь, это поможет.

РЕДАКТИРОВАТЬ:

Я не вижу ничего плохого с unValue в вашем решении, но не цитируйте меня по этому поводу. Если вы хотите избежать нотации, одним из способов является то, что вы можете использовать тот факт, что Монада также является Функтором, поэтому вы можете использовать инфикс <$>, также известный как fmap:

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