2016-07-21 18 views
6

Tôi đang cố gắng để ngăn xếp transfromers đơn nguyên của scalaz một cách Haskell:Stacking Monad Transformers trong 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 

Nó biên dịch với 1 tiềm ẩn trôi qua, nhưng không phải với 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) 
        ^

Tại sao điều này lại xảy ra? Tôi đoán là trình biên dịch bây giờ là nhầm lẫn mà "dụ monadic của F[_]" nó nên chọn (cả MonadReader và MonadState mở rộng Monad[F[_]). Đây có phải là đoán đúng không?

Cách khắc phục điều này?

+4

điểm nhỏ: Trong Haskell, tôi sẽ không gọi đây là "stad monad transformers" kể từ khi tôi sử dụng nó để tham khảo ví dụ 'StateT s (ReaderT r IO) a'. Đúng là, mặc dù vậy, trong ngăn xếp như vậy, chúng ta sẽ có nhiều ràng buộc kiểu, vì vậy nó có liên quan. – chi

+0

Tôi không nghĩ rằng hai tham số ngầm là vấn đề, nếu không bạn sẽ nhận được lỗi "giá trị tiềm ẩn mơ hồ" (xem https://github.com/scalaz/scalaz/issues/1110). – devkat

+0

@devkat nếu tôi vượt qua chỉ 1 ẩn, điều hoạt động :) –

Trả lời

1

Đây không thực sự là câu trả lời, nhưng có thể giúp ích một chút.

Tôi nghĩ bạn đã đúng; có vẻ như trình biên dịch không thể hợp nhất các loại của F[_] cả hai tham số (tôi đoán vì nó là một kiểu có mức độ cao hơn với nhiều trường hợp có thể và không phải là kiểu thể hiện cụ thể) đối với một loại đơn nguyên. Biên dịch hoạt động với các danh sách tham số riêng biệt vì việc hợp nhất loại chỉ xảy ra trong một danh sách tham số. Nó có thể được minh họa rõ hơn như thế này:

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] 

Rõ ràng, như một cách giải quyết bạn có thể sử dụng hai danh sách tham số để chọn đơn nguyên bạn muốn sử dụng:

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