Lặp đi lặp lại quy mô: Nâng lên nâng đỡ `EnumeratorT` để phù hợp với` IterateeT` cho một đơn vị lớn hơn


445

Nếu tôi có một EnumeratorTvà tương ứng, IterateeTtôi có thể chạy chúng cùng nhau:

val en: EnumeratorT[String, Task] = EnumeratorT.enumList(List("a", "b", "c"))
val it: IterateeT[String, Task, Int] = IterateeT.length

(it &= en).run : Task[Int]

Nếu đơn vị liệt kê "lớn hơn" đơn vị iteratee, tôi có thể sử dụng uphoặc nói chung hơn là Hoist"nâng" iteratee để khớp:

val en: EnumeratorT[String, Task] = ...
val it: IterateeT[String, Id, Int] = ...

val liftedIt = IterateeT.IterateeTMonadTrans[String].hoist(
  implicitly[Task |>=| Id]).apply(it)
(liftedIt &= en).run: Task[Int]

Nhưng tôi phải làm gì khi đơn vị iteratee "lớn" hơn đơn vị liệt kê?

val en: EnumeratorT[String, Id] = ...
val it: IterateeT[String, Task, Int] = ...

it &= ???

Dường như không có một Hoiství dụ nào EnumeratorT, cũng không có bất kỳ phương pháp "nâng" rõ ràng nào.


59
+1 cho một câu hỏi gọn gàng, nhưng ngoài đầu tôi không chắc chắn rằng trong trường hợp này có thể xảy ra trong trường hợp chung, vì Enumeratorthực sự chỉ là một trình bao bọc xung quanh a StepT => IterateeT, điều đó cho thấy bạn sẽ cần phải "từ chức" từ a StepT[E, BigMonad, A].
Travis Brown

12
Vâng, tôi thấy rằng khi tôi cố gắng thực hiện nó trực tiếp. Nhưng về mặt logic Enumeratorthì chỉ là một nguồn hiệu quả, phải không? Cảm giác như tôi có thể sử dụng một thứ có thể cung cấp Ađể cung cấp Task[A].
lmm

8
Tôi không biết đủ về Scala để đưa ra câu trả lời nhưng bạn không thể xác định loại của riêng mình và cung cấp cơ chế nâng cho nó ?
Cướp

8
Không, đó hoàn toàn không giống nhau, đó là một kiểu "nâng" khác.
lmm

2
@TravisBrown có một tiền thưởng cho cái này ngay bây giờ, nếu bạn muốn viết nó lên.
Aaron Hall

Câu trả lời:


4

Trong mã hóa thông thường, một điều tra viên về cơ bản là a StepT[E, F, ?] ~> F[StepT[E, F, ?]]. Nếu bạn cố gắng viết một phương thức chung chuyển đổi loại này thành một phương thức Step[E, G, ?] ~> G[Step[E, G, ?]]nhất định F ~> G, bạn sẽ nhanh chóng gặp phải một vấn đề: bạn cần "hạ thấp" Step[E, G, A]xuống một Step[E, F, A]để có thể áp dụng điều tra viên gốc.

Scalaz cũng cung cấp một mã hóa liệt kê thay thế trông như thế này:

trait EnumeratorP[E, F[_]] {
  def apply[G[_]: Monad](f: F ~> G): EnumeratorT[E, G]
}

Cách tiếp cận này cho phép chúng tôi xác định một điều tra viên cụ thể về các hiệu ứng cần thiết, nhưng điều đó có thể được "dỡ bỏ" để làm việc với những người tiêu dùng đòi hỏi bối cảnh phong phú hơn. Chúng tôi có thể sửa đổi ví dụ của bạn để sử dụng EnumeratorP(và cách tiếp cận chuyển đổi tự nhiên mới hơn thay vì thứ tự từng phần đơn nguyên cũ):

import scalaz._, Scalaz._, iteratee._, concurrent.Task

def enum: EnumeratorP[String, Id] = ???
def iter: IterateeT[String, Task, Int] = ???

val toTask = new (Id ~> Task) { def apply[A](a: A): Task[A] = Task(a) }

Bây giờ chúng ta có thể sáng tác hai cái như thế này:

scala> def result = (iter &= enum(toTask)).run
result: scalaz.concurrent.Task[Int]

EnumeratorPlà monadic (nếu Flà applicative), và EnumeratorPđối tượng bạn đồng hành cung cấp một số chức năng để giúp đỡ với điều tra viên xác định rằng trông rất giống những người trên EnumeratorTcủa -Có empty, perform, enumPStream, vv Tôi đoán có phải là EnumeratorTtrường hợp mà không thể được thực hiện bằng các EnumeratorPmã hóa, nhưng ra khỏi đỉnh đầu của tôi tôi không chắc chắn những gì họ sẽ trông như thế nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.