map[F[_]]:: [A,B] => (A=>B) => F[A] => F[B]
[A,B](A => B)F[_] (коллекции List[_], потоки данных Stream[_], ...)F[A] => F[B]flatMap[F[_]]:: [A,B] => F[A] => (A=>F[B]) => F[B]
bind[F[_]]:: [A,B] => (A=>F[B]) => F[A] => F[B]
map сигнатурой пользовательской функцииF[_] с такой операцией называется монадой)Значение F[A] может иметь несколько структурных форм, укладывающихся в шаблоны.
Каждую форму можно обработать отдельно.
unapply[F[_]]:: [A,B] => F[A] => (*[A]=>B)* => B
(*[A]=>B)* - условное обозначение, несколько функций на все случаи, возможные в F[_]List.unapply::[A,B] => List[A] => /*cons*/((A,List[A])=>B), /*nil*/(=>B) => B - структура списка полностью разбирается парой функций - для пустого и непустого спискаBoolean.unapply::[B] => Boolean => /*true*/(=>B), /*false*/(=>B) => B - if - тоже является деконструктором типа Booleanenum Enum = e1|e2|e3
Enum.unapply:: Enum => /*e1*/(=>B), /*e2*/(=>B), /*e3*/(=>B) => B
ABSF[_]трансдьюсер:
A => S => (S, F[B])
"Алгебры": лирическое отступление
"Алгебры": IO
IO[T] - вычисление, возвращающее величину T (или исключение)io.UnsafeRunSync(iot) - фактически запустить вычисление"Алгебры": Stream
Stream[T] - абстрактный поток значений типа T, который может быть превращён в вычисление io.IO[[]T]IO[A]Stream[A]
type IO[A any] Continuation[A]
type Continuation[A any] func() ResultOrContinuation[A]
type ResultOrContinuation[A any] struct {
Value A
Error error
Continuation *Continuation[A]
}
Continuation[A] - для "трамполайнинга"func StreamFold[A any, B any]( stm Stream[A], onFinish func() io.IO[B], onValue func(a A, tail Stream[A]) io.IO[B], onEmpty func(tail Stream[A]) io.IO[B], onError func(err error) io.IO[B], ) io.IO[B]
IO
type Stream[A any] io.IO[StepResult[A]]
type StepResult[A any] struct {
Value A
HasValue bool // models "Option[A]"
Continuation Stream[A]
IsFinished bool // true when stream has completed
}
IO порождает либо ошибку, либо результат
def fib(prev: BigInt, b: BigInt): Stream[Pure, BigInt] =
Stream.emit(b) ++ fib(b, prev + b)
val fib01 = fib(0, 1)
assert(fib01.take(5).toList == List(1, 1, 2, 3, 5))
assert(fib01
.map(_.pow(2))
.filter(_ % 2 == 1)
.take(5).toList == List(1, 1, 9, 25, 169)
)
assert(fib01.drop(55).head.toList ==
List(BigInt(225_851_433_717L))
func Fib(prev int, b int) Stream[int] {
return AndThenLazy(Emit(b), func() Stream[int] {
return Fib(b, prev+b)
})
}
var fibs01 = stream.Fib(0, 1)
func TestFibs(t *testing.T) {
powered := stream.Map(fibs01, pow2)
filtered := stream.FilterNot(powered, isEven)
filtered5 := stream.Take(filtered, 5)
expected := []int{1, 1, 9, 25, 169}
assert.ElementsMatch(t, expected, UnsafeStreamToSlice(t, filtered5))
}
hIO := stream.Head(stream.Drop(fib01, 55))
assert.Equal(t, int64(225851433717), UnsafeIO(t, hIO))
Спасибо за внимание
Арсений Александрович Жижелев, Праймтолк / zhizhelev@primetalk.ru