从类型款式上看Process是个对O类型值进行F运算的节点,那么scalaz-stream就应该是个运算流了。...)) //> p : scalaz.stream.Process[scalaz.concurrent.Task,Int] = Append(Halt(End),Vector()...) 2 Process.range(1,2,3).toSource //> res4: scalaz.stream.Process[scalaz.concurrent.Task...[scalaz.concurrent.Task,Int] = Await(scalaz.concurrent.Task@56aac163,,) 对stream...,然后是scalaz-stream的具体应用
我们在上一篇讨论中介绍了一些基本的由scalaz提供的typeclass。这些基本typeclass主要的作用是通过操作符来保证类型安全,也就是在前期编译时就由compiler来发现错误。...在这篇讨论中我希望能按照scalaz的格式设计自己的typeclass并能使之融入scalaz库结构里去。 我们来设计一个NoneZero typeclass。...我们按scalaz惯例在object NonZero放一个默认隐式转换: 1 object NonZero { 2 def create[A](f: A => Boolean): NonZero....NonZero[String] = scalaz.ex5$NonZero$$anon$1@ 6 /....NonZero[Boolean] = scalaz.ex5$NonZero$$anon$ 9 //
一个完整的scalaz-stream有以下几个部分组成:Source -> Transducer -> Sink,用直白文字来描述就是:“输入 -> 传换 -> 输出”。...scalaz-stream最基本的功能就是从Source接收一串元素,经过处理然后输出。毕竟我们从外部获取了数据、处理完毕后总不能就留在原地内存,还是要把数据输出到对当前运算中程序来说的一个外部系统。...[scalaz.concurrent.Task,String] = Append(Await(scalaz.concurrent.Task@702b8b12,,<function1...与上面例子不同的是它只有一个输出口: 1 import scalaz._ 2 import Scalaz._ 3 import scalaz.stream._ 4 import scalaz.concurrent...[[x]scalaz.concurrent.Task[x],Line => scalaz.concurrent.Task[Unit]] = Append(Halt(End),Vector(<function1
4 //> res6: scalaz.stream.Process[scalaz.concurrent.Task,Int] = Await(scalaz.concurrent.Task@63e2203c...[scalaz.concurrent.Task,A] 6 val es1 = emitSeq(Seq(1,2,3)) //> es1 : scalaz.stream.Process...[scalaz.concurrent.Task,Int] = Append(Await(scalaz.concurrent.Task@2d6eabae,,),...: scalaz.stream.Process[scalaz.concurrent.Task,Array[Byte]] = Await(scalaz.concurrent.Task@15de0b3c,<...scalaz-stream的其他类型节点将在下面的讨论中深入介绍。
那么scalaz-stream是怎么做到从下游运行上游定义的finalizer呢?...scalaz-stream在io对象里提供了一个linesR函数。...[scalaz.concurrent.Task,String] = Await(scalaz.concurrent.Task@6279cee3,,) 3 val...[[x]scalaz.concurrent.Task[x],String] = Append(Await(scalaz.concurrent.Task@6279cee3,,,) 5 iterLines.take
1 import scalaz.stream._ 2 import scalaz.concurrent._ 3 object streamApps { 4 import Process._ 5 def...= await(getInput)(i => emit(i * 3)) //> prg : scalaz.stream.Process[scalaz.concurrent.Task,Int]...那么如果需要不断重复运算呢: 1 import scalaz._ 2 import Scalaz._ 3 import scalaz.concurrent._ 4 import scalaz.stream...scalaz-stream就是存粹的泛函类型,那么基于scalaz-stream的程序就自然具备组合的能力了。...我们可以用两个独立的程序来示范Process程序组合: 1 import scalaz._ 2 import Scalaz._ 3 import scalaz.concurrent._ 4 import
这样也说得过去:它让我们更容易理解scalaz-stream Process的运算过程。面对scalaz-stream这样的特性我们应该怎样去实现它的并行运算呢?.../Tiger/Tee.scala" 6 //> p3 : scalaz.stream.Process[scalaz.concurrent.Task,String] = Await(scalaz.concurrent.Task...(s.length); s} //> pc : scalaz.stream.Process[scalaz.concurrent.Task,String] = Await(scalaz.concurrent.Task...[scalaz.concurrent.Task,scalaz.stream.Process[scalaz.concurrent.Task,Map[Char,Int]]] = Append(Halt(End...[scalaz.concurrent.Task,scalaz.stream.Process[scalaz.concurrent.Task,Map[Char,Int]]] = Append(Halt(End
scalaz是通过几个运算函数来提供Free Interpreter,包括:fold,foldMap,foldRun,runFC,runM。...) 15 _ <- Push(5) 16 _ <- Mul() 17 } yield () //> ast : scalaz.Free...[[x]scalaz.Coyoneda[Exercises.interact.Calc,x],Unit] = Gosub() 从Calc无法获取B类型值,所以无法实现Calc.map,因而Calc无法成为
好了,既然scala Future的功能已经比较完善了,那么scalaz的Future又有什么不同的特点呢?...所以我们是无法使用scala Future来编写纯函数的,那么在scalaz里就必须为并发编程提供一个与scala Future具同等功能但又不会立即产生副作用的类型了,这就是scalaz版本的Future...我们看看scalaz是如何定义Future的:scalaz.concurrent/Future.scala sealed abstract class Future[+A] { ... object Future...scalaz Future的构建方式如下: 1 import scalaz._ 2 import Scalaz._ 3 import scalaz.concurrent._ 4 import scala.concurrent.duration...scalaz提供了concurrent.Task类型填补了Future的这部分缺陷。我们会在下篇讨论Task。
相信许多人对scalaz-stream如何实现无穷数据的运算安全都充满了好奇和疑问,那我们就在本篇讨论中分析一下scalaz-stream的具体运算方式。 ...//> res9: scalaz.stream.Process[scalaz.concurrent.Task,Int] = Await(scalaz.concurrent.Task@7e2d773b,,) 2 eval...(Task.delay {3}) //> res10: scalaz.stream.Process[scalaz.concurrent.Task,Int...[scalaz.concurrent.Task,Int] = Await(scalaz.concurrent.Task@2173f6d9,,) 7 // Await
scalaz....: scalaz....: scalaz....: scalaz....[(scalaz.
}.repeat 7 //> addPosfix: => scalaz.stream.Process1[Int,String...[scalaz.concurrent.Task,Int] = Append(Halt(End),Vector()) 3 val seq = emitAll(Seq("a","b...","c")) //> seq : scalaz.stream.Process0[String] = Emit(List(a, b, c)) 4 val signalw...= Process(true,true,false,true) //> signalw : scalaz.stream.Process0[Boolean] = Emit(WrappedArray...[Int,String,scalaz.stream.ReceiveY[Int,String]] = Await(Left,,) 3 source.wye(seq
._ 3 import Scalaz._ 4 import scala.language.higherKinds 5 import scala.language.implicitConversions...[[x]scalaz.Coyoneda[run.demo.Modules.FreeProgs.F1,x],String]....我初步分析可能是因为scalaz对Free设下的门槛:F[A]必须是个Functor。...好了,下面是这个示范的完整源代码: 1 package run.demo 2 import scalaz._ 3 import Scalaz._ 4 import scala.language.higherKinds...242 } 243 import scalaz.Free.Trampoline 244 import scalaz.Trampoline._ 245 def runTrampoline
fs2是scalaz-stream的最新版本,沿用了scalaz-stream被动式(pull model)数据流原理但采用了全新的实现方法。...fs2比较scalaz-stream而言具备了:更精简的基础组件(combinator)、更安全的类型、资源使用(type safe, resource safety)、更高的运算效率。...由于fs2基本沿用了scalaz-stream的原理,所以我们会在下面的讨论里着重介绍fs2的使用。...我们知道,纯数据流就是scalaz-stream里的Process1,即transducer,是负责对流进行状态转换的。
fs2在处理异常及资源使用安全方面也有比较大的改善。fs2 Stream可以有几种方式自行引发异常:直接以函数式方式用fail来引发异常、在纯代码里隐式...
fs2的多线程编程模式不但提供了无阻碍I/O(java nio)能力,更为并行运算提供了良好的编程工具。在进入并行运算讨论前我们先示范一下fs2 pip...
幸运的是我们现在有了scalaz,它使我们在泛函编程的道路上节省了一大段路程。 scalaz是一套用scala语言编写的函数库。scalaz为用户提供了大量的数据类型和组件函数来支持函数式编程。...实际上scalaz的代码贡献者们是受到了纯函数式编程语言haskell的启发,把haskell中的数据类型、结构、函数组件在scalaz中用scala进行了重新实现。...既然我们打算采用scala的FP,我们可能必须把scalaz作为基础组件库来使用,那么我们必须首先了解scalaz的库结构、里面各种数据类型和组件函数、掌握它们的使用方式以及应用模式。 ...当然,在学习和介绍scalaz的过程中我们还可以更多了解scala的函数式编程模式以及它所著名的贴切简洁的表现形式。 让我们期待这个系列的scalaz讨论能真正的把我们带入函数式编程范畴的世界。。。
scalaz-stream的流程控制和多线程运算模式可以实现程序的安全并行运算。...我们先从一个简单的Free Monad程序开始: 1 import scalaz._ 2 import Scalaz._ 3 import scalaz.concurrent._ 4 import...[scalaz.Scalaz.Id[Unit]] = scalaz.concurrent.Task@282ba1e 这样我们就获得了一个异线程的延迟运算。...: scalaz.stream.Process[scalaz.concurrent.Task,scalaz.Scalaz.Id[Unit]] = Await(scalaz.concurrent.Task...我把这节讨论的示范源代码提供给大家: 1 import scalaz._ 2 import Scalaz._ 3 import scalaz.concurrent._ 4 import scalaz.stream
operation is:") 6 _ <- answer(fn,sn,op) 7 } yield() //> prg : scalaz.Free...operation is:") 33 _ <- answer(fn,sn,op) 34 } yield() //> prg : scalaz.Free...) 15 _ <- Push(5) 16 _ <- Mul() 17 } yield () //> ast : scalaz.Free...[[x]scalaz.Coyoneda[Exercises.interact.Calc,x],Unit] = Gosub() 从上面的AST表达方式可以估计到这是一个对Int进行加减乘除的计算器,应该是先通过
Scalaz里的Coyoneda与任何F[_]类型成同构(互等),而Coyoneda是个Functor,这样我们可以用Coyoneda来替代F。...我们来看看Coyoneda的定义:scalaz/Coyoneda.scala sealed abstract class Coyoneda[F[_], A] { coyo => /** The pivot...而Coyoneda和F同构,看下面scalaz里的代码: type CoyonedaF[F[_]] = ({type A[α] = Coyoneda[F, α]}) import Isomorphism
领取专属 10元无门槛券
手把手带您无忧上云