我经常遇到以下情况:假设我有这三个功能
def firstFn: Int = ...
def secondFn(b: Int): Long = ...
def thirdFn(x: Int, y: Long, z: Long): Long = ...
Run Code Online (Sandbox Code Playgroud)
我也有calculate功能.我的第一种方法可能如下所示:
def calculate(a: Long) = thirdFn(firstFn, secondFn(firstFn), secondFn(firstFn) + a)
Run Code Online (Sandbox Code Playgroud)
它看起来很漂亮,没有任何花括号 - 只有一个表达式.但它不是最佳的,所以我最终得到了这个代码:
def calculate(a: Long) = {
val first = firstFn
val second = secondFn(first)
thirdFn(first, second, second + a)
}
Run Code Online (Sandbox Code Playgroud)
现在有几个用大括号括起来的表达式.在这样的时刻,我羡慕Clojure一点点.使用let函数我可以在一个表达式中定义此函数.
所以我的目标是calculate用一个表达式定义函数.我想出了两个解决方案.
1 - 使用scalaz我可以像这样定义它(有更好的方法用scalaz做到这一点吗?):
def calculate(a: Long) =
firstFn |> {first => secondFn(first) |> {second => …Run Code Online (Sandbox Code Playgroud) 也许我错过了一些明显的东西,但我正在尝试清理一个使用Scalaz 7的项目中的一些样板,而我找不到一个看似非常简单且可能有用的特殊拼图.
假设我们有两种类型的双射:
case class Foo(x: Int)
case class Bar(i: Int)
import scalaz._, Scalaz._, BijectionT._
val fb: Foo <@> Bar = bijection[Id, Id, Foo, Bar](
foo => Bar(foo.x),
bar => Foo(bar.i)
)
Run Code Online (Sandbox Code Playgroud)
现在假设我们发现我们需要List[Foo]和之间的双射List[Bar].我们可以轻松编写一个提供此功能的隐式类(实际上我们也可以使它适用于任何仿函数):
implicit class BijectionLifter[A, B](val bij: A <@> B) extends AnyVal {
def liftInto[F[_]: Functor]: F[A] <@> F[B] = bijection[Id, Id, F[A], F[B]](
_ map bij.to,
_ map bij.from
)
}
Run Code Online (Sandbox Code Playgroud)
请注意,这是bimapHaskell的直接翻译Data.Bijection.Scalaz的双射也有一个名为的方法bimap,但它有一个更繁忙的类型,似乎没有以任何明显的方式做我想要的.
现在我们可以写下面的内容:
fb.liftInto[List]
Run Code Online (Sandbox Code Playgroud)
我们得到了我们需要的双射.
我是否遗漏了一些抽象,这使得我可以用Scalaz 7中已经提供的用于双射的函数和实例更清晰地编写它?
什么是Comonad,如果可以用Scala语法描述的话.我发现了scalaz库的实现,但目前还不清楚它在哪里有用.
scalaz.Validation据说比Trymonad 更强大,因为它可以累积错误.
是否有任何情况下,您可以选择Try在scalaz.Validation或scalaz.\/ ?
在将状态与Either进行整合(幻灯片88)时,给定State分层下的模式Either,是否有建议的方法来添加另一种类型的状态,例如,通过类似的方式记录Writer?看来新的国家有现有之间的生活State和Either为了利用快速失败行为Either中flatMap.
下面是演示代码的可运行示例,调整为使用Scalaz 7.2.8在2.11.8上工作.有没有一种方法可以在现有行为的基础上干净地添加新的monad变换器,简化了重构?在Scalaz中堆叠StateT适用于堆叠,但不处理由故障快速flatMap行为创建的排序问题Either.
// Based on slide 88+ in https://speakerdeck.com/mpilquist/scalaz-state-monad
// Adjusted for Scala 2.11 (invariant A), Scalaz 7.2 (Pointed->Applicative) and Throwable on lhs of Either
object IntegratingStateAndEither {
import scalaz._
import scalaz.Scalaz._
import EitherT._
import scalaz.StateT.stateMonad
type QueryStateS[A] = State[QueryState, A]
type ET[F[_], A] = EitherT[F, Throwable, A]
type QueryStateES[A] = ET[QueryStateS, A]
object QueryStateES …Run Code Online (Sandbox Code Playgroud) 假设我想编写一个带有以下签名的方法:
def parse(input: List[(String, String)]):
ValidationNel[Throwable, List[(Int, Int)]]
Run Code Online (Sandbox Code Playgroud)
对于输入中的每对字符串,它需要验证两个成员都可以解析为整数,并且第一个成员小于第二个.然后它需要返回整数,累积任何出现的错误.
首先,我将定义一个错误类型:
import scalaz._, Scalaz._
case class InvalidSizes(x: Int, y: Int) extends Exception(
s"Error: $x is not smaller than $y!"
)
Run Code Online (Sandbox Code Playgroud)
现在我可以按如下方式实现我的方法:
def checkParses(p: (String, String)):
ValidationNel[NumberFormatException, (Int, Int)] =
p.bitraverse[
({ type L[x] = ValidationNel[NumberFormatException, x] })#L, Int, Int
](
_.parseInt.toValidationNel,
_.parseInt.toValidationNel
)
def checkValues(p: (Int, Int)): Validation[InvalidSizes, (Int, Int)] =
if (p._1 >= p._2) InvalidSizes(p._1, p._2).failure else p.success
def parse(input: List[(String, String)]):
ValidationNel[Throwable, List[(Int, Int)]] = input.traverseU(p =>
checkParses(p).fold(_.failure, checkValues …Run Code Online (Sandbox Code Playgroud) 有一个伟大的教程在这里,这似乎暗示,我认为作家单子基本上是做代表的工作的特殊情况,元组对象(A,B).作者在左边积累了值(即A),并且A与它有相应的Monoid(因此它可以累积或改变状态).如果A是一个集合,那么它就会累积.
State Monad也是一个处理内部元组的对象.它们都可以是flatMap'd,map'd等等.这些操作对我来说都是一样的.他们有什么不同?(请用scala示例回复,我不熟悉Haskel).谢谢!
我正在学习Scalaz,我有一个已经使用Scalaz7的项目.关注这个问题我想使用这个功能
sequence[T](l: List[Option[T]]): Option[List[T]]
Run Code Online (Sandbox Code Playgroud)
(并不是说我自己写的很难).但上述问题提到了Scalaz6.
在Scalaz7中哪里可以找到序列函数?
我试图了解背后scalaz concurrent包,主要是未来和任务类的想法和目的,但在一些应用程序中使用它们时,它现在从简单的顺序模拟远,然而scala.concurrent.Future,更多的工作更好地然后.任何人都可以分享他使用scalaz编写并发/异步应用程序的经验,基本上如何async正确使用它的方法?据我所知,从源代码async不使用单独的线程,如调用标准future,或fork/applyscalaz工作的方法,那么为什么它被调用async呢?这是否意味着为了与scalaz实现真正的并发,我总是要调用fork(now(...))或apply?
假设我想从2个远程服务聚合数据,并尽可能快地提供响应:
def loadUser: Future[User]
def loadData: Future[Data]
case class Payload(user: User, data: Data)
Run Code Online (Sandbox Code Playgroud)
我知道这个顺序执行异步任务:
for {
user <- loadUser
data <- loadData
} yield Payload(user,data)
Run Code Online (Sandbox Code Playgroud)
虽然这个并行执行它们,因为异步任务在顺序链接之前被触发:
val userF = loadUser
val dataF = loadData
for {
user <- userF
data <- dataF
} yield Payload(user,data)
Run Code Online (Sandbox Code Playgroud)
然而,差异对我来说有点过于含蓄,有些人可能最初没有注意到它.
申请人也解决了这个问题
(loadUser |@| loadData) { Payload(_,_) }
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我在应用程序和monad之间使用什么来执行并行异步计算吗?每种方法的优缺点是什么?
scala ×10
scalaz ×10
monads ×4
scalaz7 ×3
either ×2
state-monad ×2
validation ×2
applicative ×1
asynchronous ×1
bijection ×1
clojure ×1
comonad ×1
concurrency ×1
functor ×1
let ×1
scala-cats ×1
writer-monad ×1