给定一个类型类,其中应根据返回类型执行实例选择:
case class Monoid[A](m0: A) // We only care about the zero here
implicit def s[T] : Monoid[Set[T]] = Monoid(Set.empty[T])
implicit def l[T] : Monoid[List[T]] = Monoid(List.empty[T])
def mzero[A](implicit m: Monoid[A]) : A = m.m0
Run Code Online (Sandbox Code Playgroud)
为什么Scala(2.11.6)无法解析正确的实例:
scala> mzero : List[Int]
<console>:24: error: ambiguous implicit values:
both method s of type [T]=> Monoid[Set[T]]
and method l of type [T]=> Monoid[List[T]]
match expected type Monoid[A]
mzero : List[Int]
^
Run Code Online (Sandbox Code Playgroud)
当它有没有问题,使用时发现基于返回类型的隐式隐函数(我们在这里重新定义它为我来说明它是多么相似mzero)
def i[A](implicit a : A) : …Run Code Online (Sandbox Code Playgroud) 鉴于eithers的序列Seq[Either[String,A]]与Left作为一个错误消息.我想获得一个Either[String,Seq[A]]在那里我得到了Right(这将是一个Seq[A]),如果序列的所有元素Right.如果至少有一个Left(错误消息),我想获取第一条错误消息或所有错误消息的串联.
当然你可以发布scalaz代码,但我也对不使用它的代码感兴趣.
我改变了标题,最初要求Either[Seq[A],Seq[B]]反映信息的正文.
我在许多项目中使用Scalaz 7的迭代,主要用于处理大型文件.我想开始切换到Scalaz 流,这些流旨在取代iteratee包(坦率地说它缺少很多部分并且使用起来很麻烦).
Streams基于机器(iteratee理念的另一种变体),它也已在Haskell中实现.我已经使用了Haskell机器库,但机器和流之间的关系并不是完全明显的(至少对我来说),并且流库的文档仍然有点稀疏.
这个问题是关于一个简单的解析任务,我希望看到使用流而不是迭代来实现.如果没有其他人能打败我,我会自己回答这个问题,但我确信我不是唯一一个正在(甚至考虑)这种转变的人,因为无论如何我需要完成这项工作,想我不妨在公共场合做这件事.
假设我有一个包含已被标记化并用词性标记的句子的文件:
no UH
, ,
it PRP
was VBD
n't RB
monday NNP
. .
the DT
equity NN
market NN
was VBD
illiquid JJ
. .
Run Code Online (Sandbox Code Playgroud)
每行有一个标记,单词和词性由单个空格分隔,空白行表示句子边界.我想解析这个文件并返回一个句子列表,我们也可以将它们表示为字符串元组的列表:
List((no,UH), (,,,), (it,PRP), (was,VBD), (n't,RB), (monday,NNP), (.,.))
List((the,DT), (equity,NN), (market,NN), (was,VBD), (illiquid,JJ), (.,.)
Run Code Online (Sandbox Code Playgroud)
像往常一样,如果我们遇到无效输入或文件读取异常,我们希望优雅地失败,我们不想担心手动关闭资源等.
首先是一些常规文件读取的东西(它应该是iteratee包的一部分,它目前不提供远程高级别的任何东西):
import java.io.{ BufferedReader, File, FileReader }
import scalaz._, Scalaz._, effect.IO
import iteratee.{ Iteratee => I, _ …Run Code Online (Sandbox Code Playgroud) 对于monad M,是否有可能A => M[B]变成M[A => B]?
我试过跟踪这些类型无济于事,这让我认为这是不可能的,但我想我还是会问.此外,搜索Hoogle a -> m b -> m (a -> b)没有返回任何东西,所以我不会抱太多运气.
Scala Future(在2.10和现在的2.9.3中是新的)是一个应用程序的函子,这意味着如果我们有一个可遍历的类型 F,我们可以使用F[A]一个函数A => Future[B]并将它们变成一个函数Future[F[B]].
此操作在标准库中可用Future.traverse.如果我们从库中导入applicative functor实例,Scalaz 7还提供了更通用的功能.traverseFuturescalaz-contrib
这两种traverse方法在流的情况下表现不同.标准库遍历在返回之前使用流,而Scalaz会立即返回未来:
import scala.concurrent._
import ExecutionContext.Implicits.global
// Hangs.
val standardRes = Future.traverse(Stream.from(1))(future(_))
// Returns immediately.
val scalazRes = Stream.from(1).traverse(future(_))
Run Code Online (Sandbox Code Playgroud)
还有另一个不同之处,正如Leif Warner 在此观察到的那样.标准库traverse立即启动所有异步操作,而Scalaz启动第一个,等待它完成,启动第二个,等待它,依此类推.
通过编写一个将为流中的第一个值休眠几秒钟的函数来显示第二个差异非常容易:
def howLong(i: Int) = if (i == 1) 10000 else 0
import scalaz._, Scalaz._ …Run Code Online (Sandbox Code Playgroud) 我对traverse,traverseU和traverseM的使用案例感到困惑,我在scalaz网站上搜索了它,简单的代码示例:
def sum(x: Int) = x + 1
List(1,2,3).traverseU(sum)
Run Code Online (Sandbox Code Playgroud)
看起来它类似于(地图和聚合):
List(1,2,3).map(sum).reduceLeft(_ + _)
Run Code Online (Sandbox Code Playgroud)
我认为它不仅仅是针对traverseU,我只是想知道这三种方法之间有什么区别,我会有更好的示例代码来显示差异
提前谢谢了
SOOOO ...
Semigroups,Monoids,Monads,Functors,Lenses,Catamorphisms,Anamorphisms,Arrows ......这些听起来都很好,经过一两次(或十次)运动后,你可以掌握它们的本质.而且Scalaz,你可以免费获得它们......
然而,就现实世界的编程而言,我发现自己很难找到这些概念的用法.是的,当然我总是在网上找到一个人在Scala上使用Monads for IO或Lenses,但是......仍然......
我试图找到的是模式的"规定"线.类似的事情:"在这里,你试图解决这个问题,解决这个问题的一个好方法是用这种方式使用镜头!"
建议?
更新:沿着这些方面,有一两本书的内容会很棒(感谢Paul):Java核心库中的GoF设计模式示例
我希望能够将操作f: (T,T) => T应用于Option[T]Scala中的值.我希望结果是None两个值中的任何一个None.
更具体地说,我想知道是否有更短的方法来执行以下操作:
def opt_apply[T](f: (T,T) => T, x: Option[T], y: Option[T]): Option[T] = {
(x,y) match {
case (Some(u),Some(v)) => Some(f(u,v))
case _ => None
}
}
Run Code Online (Sandbox Code Playgroud)
我试过了,(x zip y) map {case (u,v) => f(u,v)}但结果Iterator[T]却不是Option[T].
我想把a List[Option[T]]变成a Option[List[T]].函数的签名类型是
def lo2ol[T](lo: List[Option[T]]): Option[List[T]]
Run Code Online (Sandbox Code Playgroud)
预期的行为是将仅包含Somes 的列表映射到Some包含元素内部元素的列表Some.另一方面,如果输入列表至少有一个None,则预期的行为是返回None.例如:
scala> lo2ol(Some(1) :: Some(2) :: Nil)
res10: Option[List[Int]] = Some(List(1, 2))
scala> lo2ol(Some(1) :: None :: Some(2) :: Nil)
res11: Option[List[Int]] = None
scala> lo2ol(Nil : List[Option[Int]])
res12: Option[List[Int]] = Some(List())
Run Code Online (Sandbox Code Playgroud)
没有scalaz的示例实现将是:
def lo2ol[T](lo: List[Option[T]]): Option[List[T]] = {
lo.foldRight[Option[List[T]]](Some(Nil)){(o, ol) => (o, ol) match {
case (Some(x), Some(xs)) => Some(x :: xs);
case _ => None : Option[List[T]];
}}} …Run Code Online (Sandbox Code Playgroud) 当您的计算步骤是独立的时,通常会提到应用仿函数作为monad的替代.他们经常提到的一个优点是,当你想要堆叠应用程序时,你不需要变换器,因为F[G[X]]它总是一个应用程序.假设我有以下功能:
def getDataOption(): Option[Data]
def getUserFuture(): Future[User]
def process(data: Data, user: User)
Run Code Online (Sandbox Code Playgroud)
我想有优雅的堆叠,以获得Future[Option[User]]与Future[Option[Data]]和地图与process.
到目前为止,我只想出了这个(使用Cats):
Applicative[Future]
.compose[Option]
.map2(
Applicative[Future].pure(getDataOption()),
getUserFuture().map(Applicative[Option].pure))(process)
Run Code Online (Sandbox Code Playgroud)
但我相信这远非理想.是否有更优雅和通用的方式来实现相同的目标?
scala ×10
scalaz ×10
applicative ×1
concurrency ×1
future ×1
haskell ×1
implicit ×1
iterate ×1
option ×1
return-type ×1
scala-cats ×1