2016-07-21 27 views
6

Bir haskell şekilde scalaz arasında monad transfromers yığını çalışıyorum içinde:İstifleme Monad Transformers scala

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

scala:

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 

Odada 1 örtük geçti, ancak 2 ile birlikte derler :

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) 
        ^

Bu neden oluyor? Benim tahminim, derleyicinin şimdi "F[_] monadik örneğinin" seçilmesi gerektiğidir (hem MonadReader hem de MonadState, Monad[F[_]'u uzatır). Bu doğru bir tahmin mi?

Bu nasıl aşılır?

+4

Minör nokta: Haskell'de, yapmazdım Bu "istifleme monad transformatörleri" olarak adlandırıyorum çünkü bunu kullanmak için kullanacağım Durum (ReaderT r IO) a'. Yine de, böyle bir yığında, çoklu tip kısıtlamalarına sahip olacağımız doğrudur, bu yüzden ilişkilidir. – chi

+0

İki örtük parametrenin sorun olduğunu düşünmüyorum, aksi halde "belirsiz örtük değerler" hatasını alırsınız (bkz. Https://github.com/scalaz/scalaz/issues/1110). – devkat

+0

@devkat Eğer sadece 1 dolaylı geçerse, o şey işe yarar :) –

cevap

1

Bu gerçekten bir cevap değil, ama biraz yardımcı olabilir.

Sanırım haklısınız; Derleyici, her iki parametrenin de F[_] türünü birleştiremediğinden (tek bir tür için birden fazla olası örneğe sahip ve daha yüksek türde bir örnek olduğu için sanırım) bir monad tipine benzemiyor. Derleme, ayrı bir parametre listesiyle çalışır; çünkü tür birleştirme yalnızca bir parametre listesinde gerçekleşir. Ayrıca böyle tasvir edilebilir:

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] 

Açıkçası, bir geçici çözüm Kullanmak istediğiniz monad seçmek için iki parametre listelerini kullanabilir gibidir:

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