我正在学习Scalaz,我有一个已经使用Scalaz7的项目.关注这个问题我想使用这个功能
sequence[T](l: List[Option[T]]): Option[List[T]]
Run Code Online (Sandbox Code Playgroud)
(并不是说我自己写的很难).但上述问题提到了Scalaz6.
在Scalaz7中哪里可以找到序列函数?
假设我想从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之间使用什么来执行并行异步计算吗?每种方法的优缺点是什么?
这个问题并不意味着火焰诱饵!可能很明显,我最近一直在关注Scalaz.我试图理解为什么我需要库提供的一些功能.这是一些东西:
import scalaz._
import Scalaz._
type NEL[A] = NonEmptyList[A]
val NEL = NonEmptyList
Run Code Online (Sandbox Code Playgroud)
我在我的函数中放了一些println语句来查看发生了什么(除了:如果我试图避免这样的副作用,我会怎么做?).我的职责是:
val f: NEL[Int] => String = (l: NEL[Int]) => {println("f: " + l); l.toString |+| "X" }
val g: NEL[String] => BigInt = (l: NEL[String]) => {println("g: " + l); BigInt(l.map(_.length).sum) }
Run Code Online (Sandbox Code Playgroud)
然后我通过cokleisli将它们组合在一起并传入NEL[Int]
val k = cokleisli(f) =>= cokleisli(g)
println("RES: " + k( NEL(1, 2, 3) ))
Run Code Online (Sandbox Code Playgroud)
这打印什么?
f: NonEmptyList(1, 2, 3)
f: NonEmptyList(2, 3)
f: NonEmptyList(3) …Run Code Online (Sandbox Code Playgroud) 有
(Some(1), Some(2))
Run Code Online (Sandbox Code Playgroud)
我希望得到
Some((1, 2))
Run Code Online (Sandbox Code Playgroud)
并拥有
(Some(1), None)
Run Code Online (Sandbox Code Playgroud)
我希望得到
None
Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,可以对不同的后端系统进行大量调用,并希望使用for-comprehensions来简化后端系统的流程.
我希望结合使用EitherT(scalaz)和Future(scala 2.10),这样我就可以捕获第一个潜在错误(其未来或后端系统问题),并向最终用户返回相应的消息.我已经快速查看了scalaz验证,但是建议捕获第一个错误而不是所有错误都是使用EitherT.
我首先在REPL中尝试一个简单的例子,但是我收到了以下错误
错误:找不到参数F的隐含值:scalaz.Functor [scala.concurrent.Future]
import scala.concurrent._
import scalaz._
import Scalaz._
import ExecutionContext.Implicits.global
type EitherFuture[+A] = EitherT[Future, String, A]
def method1Success : EitherFuture[Int] = {
println("method 1 success")
EitherT {
Future {
1.right
}
}
}
def method2Failure : EitherFuture[Int] = {
println("method 2 failure")
EitherT {
Future {
"fail".left
}
}
}
val m1 = method1Success
// problem
m1.isRight
// problem
def methodChain1 = {
for {
a <- method1Success
b <- method2Failure
} yield b
}
Run Code Online (Sandbox Code Playgroud)
我仍然是scala和scalaz的新手,所以任何指针都会很棒. …
我目前正在开发一个小型项目(<10k loc),它主要是纯粹的,但依赖于主要基于迭代器的可变优化和一些用于重载计算的数据结构重用.
我想学习更多功能编程,并希望通过例如将可变计算包装到状态变换器monad等中来获得更多类型安全性.为此目的,存在scalaz库.
当通过使用所有奇特的功能来大规模地抽象我的计算时,我会介绍我不会摆脱的性能杀手吗?就像我的计算被蒙纳德的膝盖深深地包裹起来一样?
考虑到Scala的有限类型推断,它是否可行?我目前正在与非常大的类型签名(可能因为我不知道如何正确摆脱它们).我认为更多"功能性"将引入更多这样的锅炉板代码.
我不是在质疑功能方法是好还是坏.向Haskell提出这个问题毫无意义.我在质疑Scala是否合情合理.
(但这是一个不同的问题)
以下代码描述了对类型参数化输入对象(DiscreteFactorGraph[VariableType, FactorType[VariableType]])的迭代计算.你可以构造一个计算对象createInitialState并对其进行计算advanceState,最后从中提取一些信息marginals.
我希望在计算过程中保留因子图对象的类型(及其参数类型),以便最终的应用程序marginals产生正确的类型DiscreteMarginals[VariableType].我认为目前我只需要在计算类型(即TState)中保留变量类型,因此不使用携带因子类型.但是在不同的地方我甚DiscreteFactorGraph至需要变量的类型,所以我倾向于需要更多的类型信息在未来通过计算.
我很喜欢这部分,我希望有更好的解决方案.目前我有一个非常实用的方法,只有那三个功能.但我必须通过它们链接类型.或者,我可以将它定义为一个类,并使用所有这些类型对类进行参数化,因此我不必为每个方法重复类型参数.
object FloodingBeliefPropagationStepper extends SteppingGraphInferer {
def marginals[V <: DiscreteVariable, F <: DiscreteFactor[V]](state: FloodingBeliefPropagationStepper.TState[V,F]): DiscreteMarginals[V] =
BeliefPropagation.marginals(state._1, state._2)
def advanceState[V <: DiscreteVariable, F <: DiscreteFactor[V]](state: FloodingBeliefPropagationStepper.TState[V,F]): FloodingBeliefPropagationStepper.TState[V,F] = {
val graph = state._1
(graph,
BeliefPropagation.computeFactorMessages(
graph,
BeliefPropagation.computeVariableMessages(graph, state._2, graph.variables),
graph.factors))
}
def createInitialState[V <: DiscreteVariable, F <: DiscreteFactor[V]](graph: DiscreteFactorGraph[V, F], …Run Code Online (Sandbox Code Playgroud) 我试图了解如何使用scalaz State执行复杂的有状态计算.这是问题所在:
给定一个
List[Int]潜在的除数和一个List[Int]数字,找到一个List[(Int, Int)匹配对(除数,数字),其中允许除数最多匹配一个数.
作为测试:
def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)]
Run Code Online (Sandbox Code Playgroud)
并通过以下输入:
findMatches( List(2, 3, 4), List(1, 6, 7, 8, 9) )
Run Code Online (Sandbox Code Playgroud)
我们最多可以获得3场比赛.如果我们规定必须按照遍历列表lr的顺序进行匹配,那么匹配必须是:
List( (2, 6) , (3, 9) , (4, 8) )
Run Code Online (Sandbox Code Playgroud)
所以需要通过以下两个测试:
assert(findMatches(List(2, 3, 4), List(1, 6, 7, 8, 9)) == List((2, 6), (3, 9), (4, 8)))
assert(findMatches(List(2, 3, 4), List(1, 6, 7, 8, 11)) == List((2, 6), (4, 8)))
Run Code Online (Sandbox Code Playgroud)
这是一个迫切的解决方案:
scala> def findMatches(divs: …Run Code Online (Sandbox Code Playgroud) tl; dr:我如何做类似下面的编写代码:
def notFunctor[M[_] : Not[Functor]](m: M[_]) = s"$m is not a functor"
Run Code Online (Sandbox Code Playgroud)
' Not[Functor]',是这里的组成部分.
当'm'提供的不是Functor时,我希望它成功,否则编译器会失败.
解决:跳过问题的其余部分,然后直接回答下面的答案.
我粗略地说,我想要完成的是"负面证据".
伪代码看起来像这样:
// type class for obtaining serialization size in bytes.
trait SizeOf[A] { def sizeOf(a: A): Long }
// type class specialized for types whose size may vary between instances
trait VarSizeOf[A] extends SizeOf[A]
// type class specialized for types whose elements share the same size (e.g. Int)
trait FixedSizeOf[A] extends SizeOf[A] {
def fixedSize: Long
def sizeOf(a: A) …Run Code Online (Sandbox Code Playgroud) 在斯卡拉兹
Kleisli[F, A, B]是一个包装A => F[B].ReaderT[F, A, B]- 读者monad变换器 - 只是别名Kleisli[F, A, B].Reader[A, B]monad是ReaderT身份monad 的专长Id:type Reader[A, B] = ReaderT[Id, A, B].难道仅仅是巧合还是有一些更深层次的原因Kleisli,ReaderT以及Reader是同构的Scalaz?
我想知道我的方法应该是什么签名,以便我优雅地处理不同类型的失败.
这个问题在某种程度上是我已经在Scala中处理错误的许多问题的总结.你可以在这里找到一些问题:
现在,我理解以下内容:
存储库层
现在请考虑我有一个UserRepository.所述UserRepository存储的用户,并限定了findById方法.可能发生以下故障:
OutOfMemoryError)此外,用户可能会丢失,从而导致Option[User]结果
使用存储库的JDBC实现,可以抛出SQL,非致命异常(约束违规或其他),因此使用Try是有意义的.
当我们处理IO操作时,如果我们想要纯函数,那么IO monad也是有意义的.
所以结果类型可能是:
Try[Option[User]]IO[Option[User]]服务层
现在让我们介绍一个业务层,UserService它提供了一些updateUserName(id,newUserName)使用先前定义findById的存储库的方法.
可能发生以下故障:
然后结果类型可以是:
Try[Either[BusinessError,User]]IO[Either[BusinessError,User]]这里的BusinessError不是Throwable,因为它不是一个例外的失败.
使用for-comprehensions
我想继续使用for-comprehensions来组合方法调用.
我们不能轻易地将不同的monad混合起来进行理解,所以我想我的所有操作都应该有一些统一的返回类型吗?
我只是想知道你在现实世界的Scala应用程序中如何成功地在不同类型的故障发生时继续使用for-understanding.
对于现在来说,for-comprehension对我来说很好,使用服务和存储库都可以返回,Either[Error,Result]但是所有不同类型的故障都会融合在一起,并且处理这些故障会变得很糟糕.
您是否定义了不同类型的monad之间的隐式转换,以便能够使用for -reherehension?
你定义自己的monad来处理失败吗?
顺便说一下,我很快就会使用异步IO驱动程序.所以我想我的返回类型可能更复杂:IO[Future[Either[BusinessError,User]]]
任何建议都会受到欢迎,因为我真的不知道该使用什么,而我的应用程序并不花哨:它只是一个API,我应该能够区分可以向客户端显示的业务错误,以及技术错误.我试图找到一个优雅而纯粹的解决方案.
scala ×10
scalaz ×10
scalaz7 ×2
applicative ×1
either ×1
future ×1
implicit ×1
kleisli ×1
monads ×1
performance ×1
reader-monad ×1
scala-2.8 ×1
scala-cats ×1
shapeless ×1
typeclass ×1