2015-11-07 9 views
0

Я работаю с некоторыми вложенными Stream с и хотели бы использовать синтаксис понимания с ними:Работа с Streams завернутые в Параметрах

def handleNestedStream(as : Stream[A]) : Stream[(A, B)] = { 
    a <- as 
    b <- makeBs(a) 
} yield (a, b) 

Однако функция makeBs возвращает Option[Stream[B]]. Я бы хотел, чтобы Option был развернут автоматически. Кроме того, я хотел бы, чтобы вся функция возвращала None, если makeBs терпит неудачу. Таким образом, новая функция будет выглядеть примерно так:

def makeBs(a : A) : Option[Stream[B]] = { ... } 

def handleNestedStream(as : Stream[A]) : Option[Stream[(A, B)]] = { 
    a <- as 
    b <- makeBs(a) 
} yield (a, b) 

Единственное изменение - это тип функции.

Как я могу выполнить что-то подобное? Может ли StreamingT от кошек или StreamT от скаляса помочь здесь?

Некоторые из типов являются гибкими. makeBs может быть сделано для возврата Stream[Option[B]] вместо Option[Stream[B]], если это упростит ситуацию.

Мне нужно использовать стандарт scala lib Stream.

ответ

1

Давайте представим, что реализация

import scalaz._ 
import std.option._ 
import syntax.std.option._ 

type StreamO[X] = StreamT[Option,X] 

def makeBs(a : A) : StreamO[B] = ??? 

def handleNestedStream(as : Stream[A]) : StreamO[(A, B)] = for { 
    a <- StreamT fromStream as.some 
    b <- makeBs(a) 
} yield (a, b) 

Пусть теперь

import syntax.monad._ 
type A = Int 
type B = String 
def makeBs(a : A) = for (x <- a.point[StreamO] if x % 2 == 1) yield x.toString * x 

handleNestedStream(1 to 5 toStream).toStream 

будет оцениваться, как

Некоторые (Stream ((1,1), (3333), (5 , 55555)))

2

Другой способ сделать это состоит в использовании traverseM из scalaz:

import scalaz._, Scalaz._ 

def handleNestedStream(as : Stream[A]) : Option[Stream[(A, B)]] = 
    as.traverseM(a => makeBs(a).map(_.map(a ->))) 

Основная подпись traverseM является traverseM(fa: F[A])(f: A => G[F[B]]): G[F[B]] (F должны иметь экземпляры Traverse и Bind и G должны иметь экземпляр Applicative). В этом случае F - Stream, G - Option и B в подписи (A, B) из вашего примера.

Так что, если вы звоните traverseM на Stream[A], и хотят получить обратно Option[Stream[(A, B)]], вы должны передать его функции A => Option[Stream[(A, B)]] - это естественно makeBs, а затем глубокую карту, что делает (A, B) пары.

функции с суффиксом M (filterM, traverseM, foldLeftM и т.д.), как правило, весьма полезно, если вы хотите объединить несколько различных контекстов, но без шаблонного монады трансформаторов.