#haskell #mongodb
#haskell #mongodb
Вопрос:
Итак, идея в том, что я бы взял следующий код, используемый для выполнения запросов MongoDB в haskell
- Полный пример: https://gist.github.com/1337864
-
Введение в драйвер Haskell MongoDB: https://github.com/TonyGen/mongoDB-haskell/blob/master/doc/Example.hs
канал <- runIOE $ connect $ host «127.0.0.1» разрешить выполнение действия = доступ к мастеру канала «testdb» выполнить действие $ удалить $ выбрать [] «mycollection»
И я хотел бы превратить это в это, чтобы я мог притвориться, что функция run является «db», как в обычном драйвере mongo.
db <- connectDb "127.0.0.1" "testdb"
db $ delete $ select [] "mycollection"
Вот функция, которую я написал для этого:
mdb :: (MonadIO m) => String -> String -> IO (Action m a -> m (Either Failure a))
mdb hostname dbname = do
pipe <- runIOE $ connect $ host hostname
return (access pipe master (pack dbname))
Я получил тип, оставив его нетипизированным, а затем спросил ghci, что это за тип. Я едва понимаю это.
Итак, вот вопрос
Когда я создаю в своей программе ТОЛЬКО db <- connectDb "127.0.0.1" "testdb"
и не использую ее, она завершается с ошибкой неоднозначного типа: https://gist.github.com/1337864 — Как я могу сделать это недвусмысленным? Разве это плохая идея — создать такую абстракцию? Как бы вы это сделали?
Ответ №1:
Мне всегда хочется ответить на эти вопросы: «Это потому, что ваш тип неоднозначен». Например, если вам было присвоено значение:
MonadIO m => (Action m a -> m (Either Failure a))
И сказали, что монада m
— это конкретная монада (а не просто какая-то одна), можете ли вы сказать, какая это? Нет.
Если вы не используете возвращаемое значение в контексте, который делает очевидным, к какой монаде m
принадлежит, тогда вам нужно предоставить компилятору дополнительную информацию:
db <- connectDB "127.0.0.1" "testdb" :: IO (Action IO a -> IO (Either Failure a))
Комментарии:
1. Спасибо! Также обратите внимание, что изменение подписи mdb тоже работает. Я не понял, что я говорил с этим типом.
2. Было бы неплохо, если
MonadIO m => m
бы по умолчаниюIO
в других неоднозначных случаях.3. @Dan Burton:
-fextended-default-rules
для подобных вещей есть и соответствующая прагма. Проверьте, есть ли значения по умолчанию дляMonadIO
. Я думаю, что такое дефолтирование является злом — вот почему оно отключено по умолчанию. Одним из интересных примеров является значение по умолчаниюControl.Applicative
дляIO
.4. Единственное, что делают расширенные правила по умолчанию, это добавляют
()
в список типов по умолчанию (так что теперь()
это,Integer
иDouble
) и ослабляют ограничение на то, какие классы типов могут быть по умолчанию. По умолчанию нетIO
. Причина, по которой это может показаться, заключается в том, что при вводе выражений в GHCi сначала будет предпринята попытка запустить его какIO a
. Если это не удается, оно вычисляется и печатается как обычно. Однако это происходит только на самом внешнем уровне, поэтому любая неоднозначностьMonad m => m
в выражении не будет выполняться по умолчанию.