我想使用的状态单子转换Scalaz 7通过一个分析器,线程额外的状态,我无法做任何有用的事情而无需编写大量的t m a -> t m b版本m a -> m b的方法.
假设我有一个包含嵌套括号的字符串,其中包含数字:
val input = "((617)((0)(32)))"
Run Code Online (Sandbox Code Playgroud)
我还有一个新的变量名称流(在这种情况下是字符):
val names = Stream('a' to 'z': _*)
Run Code Online (Sandbox Code Playgroud)
我想从流的顶部拉出一个名称,并在解析它时将其分配给每个括号表达式,然后将该名称映射到表示括号内容的字符串,并将嵌套的括号表达式(如果有)替换为他们的名字.
为了使这更具体,这就是我希望输出看起来像上面的示例输入:
val target = Map(
'a' -> "617",
'b' -> "0",
'c' -> "32",
'd' -> "bc",
'e' -> "ad"
)
Run Code Online (Sandbox Code Playgroud)
在给定级别可能存在一串数字或任意多个子表达式,但这两种内容不会在单个括号表达式中混合.
为了简单起见,我们假设名称流永远不会包含重复项或数字,并且它总是包含足够的输入名称.
上面的示例是此Stack Overflow问题中解析问题的略微简化版本 .我用一个大致如下的解决方案回答了这个问题:
import scala.util.parsing.combinator._
class ParenParser(names: Iterator[Char]) extends RegexParsers {
def paren: Parser[List[(Char, String)]] …Run Code Online (Sandbox Code Playgroud) 一个用例示例:
def div2(i: Int): Validation[String, Int] =
if (i%2 == 0) Validation.success(i/2)
else Validation.failure("odd")
def div4(i: Int) = for {
a <- div2(i)
b <- div2(a)
} yield b
Run Code Online (Sandbox Code Playgroud)
错误:无法取消应用类型scalaz.Validation[String,Int]到M[_]由类型类别分类的类型构造函数scalaz.Bind
我猜错误是由编译器无法找到的Monad实例引起的Validation[String, Int]
我可以为自己制作一个,比如:
object Instances {
implicit def validationMonad[E] = new Monad[({type L[A] = Validation[E, A]})#L] {
override def point[A](a: => A) =
Validation.success(a)
override def bind[A, B](fa: Validation[E, A])(f: A => Validation[E, B]) =
fa bind f
} …Run Code Online (Sandbox Code Playgroud) 我有时会看Scalaz并发现很难理解初学者Scala程序员.
implicit def KleisliCategory[M[_]: Monad]: Category[({type ?[?, ?]=Kleisli[M, ?, ?]})#?] = new Category[({type ?[?, ?]=Kleisli[M, ?, ?]})#?] {
def id[A] = ?(_ ?)
def compose[X, Y, Z](f: Kleisli[M, Y, Z], g: Kleisli[M, X, Y]) = f <=< g
}
implicit def CokleisliCategory[M[_]: Comonad]: Category[({type ?[?, ?]=Cokleisli[M, ?, ?]})#?] = new Category[({type ?[?, ?]=Cokleisli[M, ?, ?]})#?] {
def id[A] = ?(_ copure)
def compose[X, Y, Z](f: Cokleisli[M, Y, Z], g: Cokleisli[M, X, Y]) = f =<= g
}
Run Code Online (Sandbox Code Playgroud)
Scalaz方法对于有经验的函数式程序员来说似乎是显而易见的,但对于其他任何人来说,它很难理解.
为什么Scalaz代码中的文档很少?
他们为什么要使用那么多大多数人都无法阅读的运营商?我甚至不知道如何键入 …
说我有两张地图:
val a = Map(1 -> "one", 2 -> "two", 3 -> "three")
val b = Map(1 -> "un", 2 -> "deux", 3 -> "trois")
Run Code Online (Sandbox Code Playgroud)
我想通过键合并这些映射,应用一些函数来收集值(在这种特殊情况下,我想将它们收集到一个seq中,给出:
val c = Map(1 -> Seq("one", "un"), 2 -> Seq("two", "deux"), 3 -> Seq("three", "trois"))
Run Code Online (Sandbox Code Playgroud)
感觉应该有一个很好的,惯用的方式来做这个 - 任何建议?如果解决方案涉及scalaz,我很高兴.
可能重复:
好的scalaz介绍
我想了解更多有关Scalaz的信息,可能会使用Scalaz7来避免在声明稳定后重新布线.我的问题是Scalaz包含很多功能.虽然大部分内容都是独立于其他部分,但我希望能够全面了解Scalaz提供的全局功能以及它的组织方式.据我所知,Scalaz除其他外提供了
Functor,Applicative和Monad特征,Validation(编辑:原来它只是一个应用)OptionT,EitherT....)Itereatee小号LensESZipper小号除此之外还有很多隐式转换,以及新的构造函数,例如some与标准库重叠但在类型方面表现更好
:type Some(3) // Some[Int]
:type some(3) // Option[Int]
Run Code Online (Sandbox Code Playgroud)
我对大多数这些结构有基本的把握,但我对任何概念都不熟悉.
您对以何种顺序学习库有什么建议吗?模块之间存在哪些逻辑依赖关系?更一般地说,我在哪里可以找到图书馆的高级概述?
编辑似乎大多数答案都是针对学习函数式编程的基本组件,比如monad,所以我会尝试更精确.我有Haskell的基本知识和数学家背景,所以我的问题与类别理论或基本函数式编程无关.
我的问题是Scalaz是一个庞大的图书馆.我不知道在哪里找到什么,在各种数据类型上有哪些方法可用或有用.我真正需要的是一张地图,例如,它会告诉我,当我想要迭代需要处理的资源时,我可能想要考虑迭代以及我可以用它做什么样的操作.更像是图书馆可用功能的全景.
在学习Haskell时,我发现这个问题的答案非常有用,因为它将概念与运算符联系起来:常见的Haskell运算符是否有明显的名称?
scalaz有一个等价的字典吗?或者有人可以帮助提供有关他们如何发音自己的scalaz代码的建议?
我是scalaz的新手,我试图找出以下代码的工作原理:
import scalaz._
import Scalaz._
scala> Map[String,List[String]]() |+| Map[String,List[String]]()
res3: scala.collection.immutable.Map[String,List[String]] = Map()
Run Code Online (Sandbox Code Playgroud)
但这不......
import scalaz._
import Scalaz._
scala> Map[String,Seq[String]]() |+| Map[String,Seq[String]]()
<console>:14: error: value |+| is not a member of scala.collection.immutable.Map[String,Seq[String]]
Map[String,Seq[String]]() |+| Map[String,Seq[String]]()
Run Code Online (Sandbox Code Playgroud)
我看到Semigroup隐含了Map,但我看不到List或Seq的Map.
情侣问题:
我经常遇到以下情况:假设我有这三个功能
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)Monad看起来像这样:
trait Monad[M[_]] {
def pure[A](a : A) : M[A]
def bind[A, B](ma : M[A], f : A => M[B]) : M[B]
}
Run Code Online (Sandbox Code Playgroud)
Monad Transformer是什么样的?它们用于什么?
比方说,我只是想用replicateM从Scalaz ;
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> some(4).replicateM[List](2)
res20: Option[List[Int]] = Some(List(4, 4))
Run Code Online (Sandbox Code Playgroud)
现在让我们说,而不是有一个Option[Int],我需要读取一个Int值File:
scala> val f = (_ : java.io.File) => some(1)
f: (java.io.File) => Option[Int] = <function1>
Run Code Online (Sandbox Code Playgroud)
所以,我可以对待这个读者,好像它是一个Monad?
scala> ReaderT(f).replicateM[List](2)
<console>:16: …Run Code Online (Sandbox Code Playgroud)