Anatolii
есть вот таких 2 тайп класса и по инстансу для них
Anatolii
class (Monad m) => JiraClient m where
jiraUser :: Int -> MaybeT (ExceptT MyErr m) JiraUser
instance JiraClient (State (IntMap JiraUser)) where
jiraUser id = do
db <- get
hoistMaybe $ lookup id db
class (Monad m) => RedmineClient m where
redmineUser :: Int -> MaybeT (ExceptT MyErr m) User
instance RedmineClient (State (IntMap User)) where
redmineUser id = do
db <- get
hoistMaybe $ lookup id db
Anatolii
и есть вот такая функция
func :: (RedmineClient m, JiraClient m) => MaybeT (ExceptT MyErr m) String
func = do
u1 <- jiraUser 1
u2 <- redmineUser 2
return $ show u1 ++ show u2
Anatolii
для IO есть инстансы
Anatolii
и проблем с запуском нету
Anatolii
а вот как запустить с 2-мя разными State я пока не смог додуматься
Anatolii
я пробовал через StateT сделать
Anatolii
но тоже не смог
Alexander
с мтл так не прокатит, с двумя StateT формально можно если лифты руками сделаешь
Alexander
можно посмотреть доклад кмета и про monad morphism и посмотреть не запилил ли он это
Anatolii
лифты в func делать надо?
Alexander
ну у тебя будет StateT внутри другого
Anatolii
я понял
Alexander
и для функций во внутреннем тебе придётся lift писать
Anatolii
я просто делал StateT instance
Anatolii
для каждого из клиентов
Anatolii
и думал как-то это запустить получится
Anatolii
чтобы внутри func ничего не трогать
Alexander
вообще были какие-то пакеты с проекциями или тегами
Alexander
у roche и ещё у кого-то
Anatolii
как вообще в хаскеле делают такие вещи?
ну вот я хочу изолировать IO и протестировать функцию
Anatolii
ну внутри func могла быть более сложная логика
Anatolii
каким путем идут?
Anatolii
я наверное как-то не так пошел
Alexander
2 стейта разных в mtl или что именно?
Anatolii
ну смотри, я хочу написать функцию, которой нужны данные с двух разных сервисов
Anatolii
чтобы протестировать эту логику
Anatolii
мне надо как-то изолировать сервисы
Anatolii
ну в других языках делают интерфейсы
Anatolii
и делают тестовую реализацию
Anatolii
или моки
Anatolii
как в хаскеле это делают?
Anatolii
или мне надо было делать какой-то RedmineClientT и JiraClientT ?
Alexander
ну можно как ты через класс типов для каждого сервиса
Anatolii
ну да
Alexander
MonadRedmineClient и MonadJiraClient
Anatolii
я вот так и хотел
Alexander
и instance MonadRedmineClient MyMegaMonad where ... instance MonadJiraClient MyMegaMonad where ..
Anatolii
ну вот у меня так сверху же сделано
Anatolii
или нет?
Anatolii
и что ты под MyMegaMonad понимаешь?:)
Alexander
и потом
runMyMegamonad = do {
{ a <- anyRedmineAction
; b <- anyJiraAction
}
Anatolii
не знал что тут снипеты есть:)
Alexander
newtype MyMegaMonad a = MyMegaMonad { runMyMegaMonad :: ReaderT Env (StateT (JiraState, RedmineState, Qu)) a }
deriving (Function, Applicative, Monad, MonadReader Env, MonadState (JiraState, RedmineState,Qu))
Alexander
нппример
Anatolii
ха, я думал насчет общего State
Alexander
тут у тебя проблема что ты в одном mtl хочешь 2 разных MonadState если я правильно прочитал
Anatolii
и пару положить
Anatolii
да
Alexander
в этом проблема
Anatolii
так и есть
Anatolii
да
Anatolii
я понимаю
Alexander
но к вопросу как тестируют это не сильно относится, это отдельный конкретный implementation detail
Alexander
я вообще всегда как-то по другому делаю, давай я сслки на пакеты накидаю, может что интересное найдешь
Anatolii
просто если приложение будет разростаться - то вот этот StateT будет очень сильно разростаться
Anatolii
да
Anatolii
давай
Anatolii
будет отлично
Alexander
https://hackage.haskell.org/package/monad-classes
Anatolii
а то я прочитал главу mtl в RealWorldHaskell
Anatolii
и вот пока не могу с ними подружиться
Anatolii
уже 3-ий день кручу верчу
Alexander
как по юзеру искать на hackage?
Anatolii
я не знаю:(
Alexander
http://hackage.haskell.org/package/monad-levels
Alexander
во
Alexander
ну и эффекты
Anatolii
первая от Чепляки:)
Anatolii
и серия статей даже есть
Anatolii
но судя по коду там можно сделать как раз то что я хочу
Alexander
http://hackage.haskell.org/package/extensible-effects
Anatolii
с двумя стэйтами разными:)
Alexander
http://hackage.haskell.org/package/freer
Alexander
ну я про это и говорил
Anatolii
ты вот этим всем пользуешся в таких случаях?
Alexander
у roche и ещё у кого-то
Alexander
нет : )
Anatolii
:)
Alexander
у меня честно почти не возникало ситуации когда мне нужно МонадФуБар оьъединять