标签: scalaz

Clojure在Scala中的'let'等价物

我经常遇到以下情况:假设我有这三个功能

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)

scala clojure let scalaz

22
推荐指数
2
解决办法
3670
查看次数

将双射提升为仿函数

也许我错过了一些明显的东西,但我正在尝试清理一个使用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中已经提供的用于双射的函数和实例更清晰地编写它?

scala functor bijection scalaz scalaz7

21
推荐指数
1
解决办法
569
查看次数

Scala中的Comonad示例

什么是Comonad,如果可以用Scala语法描述的话.我发现了scalaz库的实现,但目前还不清楚它在哪里有用.

monads scala scalaz comonad

20
推荐指数
2
解决办法
2495
查看次数

在Scala中处理monad时出错?尝试与验证

scalaz.Validation据说比Trymonad 更强大,因为它可以累积错误.

是否有任何情况下,您可以选择Tryscalaz.Validationscalaz.\/

validation error-handling monads scala scalaz

20
推荐指数
1
解决办法
3238
查看次数

在scalaz中分层状态

将状态与Either进行整合(幻灯片88)时,给定State分层下的模式Either,是否有建议的方法来添加另一种类型的状态,例如,通过类似的方式记录Writer?看来新的国家有现有之间的生活StateEither为了利用快速失败行为EitherflatMap.

下面是演示代码的可运行示例,调整为使用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)

scala state-monad monad-transformers either scalaz

20
推荐指数
1
解决办法
425
查看次数

验证与分离

假设我想编写一个带有以下签名的方法:

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)

validation functional-programming scala either scalaz

19
推荐指数
1
解决办法
2655
查看次数

作家Monad是否与State Monad有效?

有一个伟大的教程在这里,这似乎暗示,我认为作家单子基本上是做代表的工作的特殊情况,元组对象(A,B).作者在左边积累了值(即A),并且A与它有相应的Monoid(因此它可以累积或改变状态).如果A是一个集合,那么它就会累积.

State Monad也是一个处理内部元组的对象.它们都可以是flatMap'd,map'd等等.这些操作对我来说都是一样的.他们有什么不同?(请用scala示例回复,我不熟悉Haskel).谢谢!

monads scala state-monad scalaz writer-monad

19
推荐指数
1
解决办法
1649
查看次数

Scalaz7中的`sequence`在哪里?

我正在学习Scalaz,我有一个已经使用Scalaz7的项目.关注这个问题我想使用这个功能

sequence[T](l: List[Option[T]]): Option[List[T]]
Run Code Online (Sandbox Code Playgroud)

(并不是说我自己写的很难).但上述问题提到了Scalaz6.

在Scalaz7中哪里可以找到序列函数?

scala scalaz scalaz7

18
推荐指数
1
解决办法
2573
查看次数

了解Scalaz Future和Task的一点帮助

我试图了解背后scalaz concurrent包,主要是未来和任务类的想法和目的,但在一些应用程序中使用它们时,它现在从简单的顺序模拟远,然而scala.concurrent.Future,更多的工作更好地然后.任何人都可以分享他使用scalaz编写并发/异步应用程序的经验,基本上如何async正确使用它的方法?据我所知,从源代码async不使用单独的线程,如调用标准future,或fork/applyscalaz工作的方法,那么为什么它被调用async呢?这是否意味着为了与scalaz实现真正的并发,我总是要调用fork(now(...))apply

concurrency asynchronous scala scalaz scalaz7

18
推荐指数
1
解决办法
4176
查看次数

Monads VS期货的应用函子

假设我想从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之间使用什么来执行并行异步计算吗?每种方法的优缺点是什么?

monads scala scalaz applicative scala-cats

18
推荐指数
1
解决办法
1415
查看次数