2016-07-21 10 views
6

Я пытаюсь сложить монады transfromers из scalaz в Haskell образом:штабелирование Монада Трансформаторы в Скале

statyReader :: (MonadReader Int m, MonadState Int m) => m Int 

Скал:

def statyReader[F[_]](implicit r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] = for { 
    counter <- s.get 
    secret <- r.ask 
    _  <- s.put(counter + secret) 
    } yield counter 

Он компилирует с 1 неявными прошли, но не с 2 :

Error:(13, 18) value flatMap is not a member of type parameter F[Int] 
    counter <- s.get 
       ^
Error:(14, 18) value flatMap is not a member of type parameter F[Int] 
    secret <- r.ask 
       ^
Error:(15, 21) value map is not a member of type parameter F[Unit] 
    _  <- s.put(counter + secret) 
        ^

Почему это происходит? Я предполагаю, что компилятор теперь запутался в том, что «монадический экземпляр F[_]» он должен выбрать (оба MonadReader и MonadState продлят Monad[F[_]). Правильно ли это?

Как преодолеть это?

+4

мелочь: В Haskell, я бы не стал назовите это «укладчивые монадные трансформаторы», так как я буду использовать это для ссылки, например 'StateT s (ReaderT r IO) a'. Правда, в таком стеке у нас было бы несколько ограничений типа, поэтому оно связано. – chi

+0

Я не думаю, что эти две неявные параметры являются проблемой, иначе вы получите ошибку «неоднозначные неявные значения» (см. Https://github.com/scalaz/scalaz/issues/1110). – devkat

+0

@devkat, если я передаю только 1 неявное, вещь работает :) –

ответ

1

Это не совсем ответ, но, возможно, немного помогает.

Я думаю, что вы правы; похоже, что компилятор не может объединить типы обоих параметров (думаю, так как это более высокий тип с несколькими возможными экземплярами, а не конкретный экземпляр типа) для типа монады. Компиляция работает с отдельными списками параметров, поскольку унификация типов происходит только в списке параметров. Это может быть проиллюстрировано следующим образом:

def statyReader[F[_]](implicit r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] = 
    statyReader2(r, s) 

def statyReader2[F[_]:Monad](r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] = 
    for { 
    counter <- s.get 
    secret <- r.ask 
    _ <- s.put(counter + secret) 
    } yield counter 

Error: ambiguous implicit values: both 
value s of type scalaz.MonadState[F,Int] and 
value r of type scalaz.MonadReader[F,Int] 
match expected type scalaz.Monad[F] 

Очевидно, как обходной путь вы можете использовать два список параметров, чтобы выбрать, какую монаду вы хотите использовать:

def statyReader[F[_]](implicit r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] = 
    statyReader2(r)(s) 

def statyReader2[F[_]](r: MonadReader[F, Int])(implicit s: MonadState[F, Int]): F[Int] = 
    for { 
    counter <- s.get 
    secret <- r.ask 
    _ <- s.put(counter + secret) 
    } yield counter