为了帮助我学习Applicative Functors和Functors,我认为看看如何Either用类型类Functor和函数实现它会很有趣Applicative.显然我可以继续阅读代码,但我发现自己尝试实现一些东西以更好地理解事物更有用.
仅供参考我正在尝试实现此演示文稿结果的Haskell版本http://applicative-errors-scala.googlecode.com/svn/artifacts/0.6/chunk-html/index.html
无论如何,这是我到目前为止所拥有的
data Validation a b = Success a | Failure b deriving (Show, Eq)
instance Functor (Validation a) where
fmap f (Failure x) = Failure x
fmap f (Success x) = Success (f x)
Run Code Online (Sandbox Code Playgroud)
但每当我尝试运行此命令时,ghci我只会收到以下错误消息: -
[1 of 1] Compiling Main ( t.hs, interpreted )
t.hs:5:35:
Couldn't match type `b' with `a1'
`b' is a rigid type variable bound by
the type signature for
fmap :: (a1 -> …Run Code Online (Sandbox Code Playgroud) 我可以=在scala for-understanding中使用一个(如SLS第6.19节所述)如下:
假设我有一些功能String => Option[Int]:
scala> def intOpt(s: String) = try { Some(s.toInt) } catch { case _ => None }
intOpt: (s: String)Option[Int]
Run Code Online (Sandbox Code Playgroud)
然后我可以这样使用它
scala> for {
| str <- Option("1")
| i <- intOpt(str)
| val j = i + 10 //Note use of = in generator
| }
| yield j
res18: Option[Int] = Some(11)
Run Code Online (Sandbox Code Playgroud)
据我所知,这基本上相当于:
scala> Option("1") flatMap { str => intOpt(str) } map { …Run Code Online (Sandbox Code Playgroud) 是否有可能以Either类似的方式处理Option?在Option,我有一个getOrElse功能,在Either我想要返回Left或处理Right.我正在寻找最快的方法,没有任何样板:
val myEither:Either[String, Object] = Right(new Object())
myEither match {
case Left(leftValue) => value
case Right(righValue) =>
"Success"
}
Run Code Online (Sandbox Code Playgroud) 假设我有几个案例类和很少的函数来测试它们.
case class PersonName(...)
case class Address(...)
case class Phone(...)
def testPersonName(pn: PersonName): Either[String, PersonName] = ...
def testAddress(a: Address): Either[String, Address] = ...
def testPhone(p: Phone): Either[String, Phone] = ...
Run Code Online (Sandbox Code Playgroud)
现在我定义一个新的案例类Person和一个快速失败的测试函数.
case class Person(name: PersonName, address: Address, phone: Phone)
def testPerson(person: Person): Either[String, Person] = for {
pn <- testPersonName(person.name).right
a <- testAddress(person.address).right
p <- testPhone(person.phone).right
} yield person;
Run Code Online (Sandbox Code Playgroud)
现在我想用testPerson 它来累积错误而不是快速失败.
我想函数testPerson总是执行所有这些test*函数并返回Either[List[String], Person].我怎样才能做到这一点 ?
考虑一下代码:
val some: OneCaseClass Either TwoCaseClass = ???
val r = some.left.map(_.toString)
Run Code Online (Sandbox Code Playgroud)
为什么r是Serializable with Product with Either[String, TwoCaseClass]类型而不是Either[String, TwoCaseClass]?
如何只映射左值?
我有以下方法:
firstRightOrLefts :: [Either b a] -> Either [b] a
firstRightOrLefts eithers =
case partitionEithers eithers of
(_, (x : _)) -> Right x
(xs, _) -> Left xs
Run Code Online (Sandbox Code Playgroud)
困扰我的是丑陋的模式匹配,我想知道是否有更惯用的方法来编写这种方法.我的想法是,我有一堆可以返回Eithers的计算,我只想获得第一个结果或所有错误消息.也许我使用了错误的数据结构.也许Writer monad会更适合这项任务.我现在真的不确定.欢呼任何帮助!
Java 8中的monadic编程是否更慢?下面是我的测试(使用右偏置的Either为每次计算创建新实例).命令式版本快1000倍.如何在Java8中编程monadicaly同时获得可比性能?
Main.java
public class Main {
public static void main(String args[]){
Main m = new Main();
m.work();
m.work2();
}
public void work(){
final long start = System.nanoTime();
final Either<Throwable,Integer> result =
Try(this::getInput).flatMap((s) ->
Try(this::getInput).flatMap((s2) ->
parseInt(s).flatMap((i) ->
parseInt(s2).map((i2) ->
i + i2
))));
final long end = System.nanoTime();
result.map(this::println).leftMap(this::println);
System.out.println((end-start)/1000+"us to execute");
}
public void work2(){
Object result;
final long start = System.nanoTime();
try {
final String s = getInput();
final String s2 = getInput();
final int i = …Run Code Online (Sandbox Code Playgroud) 我是一个Haskell新手,我想知道为什么没有替代实例,Either但是半群,其行为与我期望的替代:
instance Semigroup (Either a b) where
Left _ <> b = b
a <> _ = a
Run Code Online (Sandbox Code Playgroud)
此实例丢弃或更正"错误",当两个操作数都被标记时Right,它将采用第一个.这不是替代品提供的"选择"吗?
我希望semigroup实例看起来大致如下:
instance (Semigroup b) => Semigroup (Either a b) where
Left e <> _ = Left e
_ <> Left e = Left e
Right x <> Right y = Right (x <> y)
Run Code Online (Sandbox Code Playgroud)
这意味着它传播错误并附加常规结果.
我想我有一个错误的概念Either或涉及的类型类.
我从一些人那里听说,在Scala中,我们倾向于(像其他函数式语言一样)不打破控制流...相反,按惯例,我们返回错误Either Left.
但是我们如何从这个例外中得到stracktrace呢?现在我在左边返回一个Error带有代码,消息和原因的简单案例类(Error也是).但如果我有错误,我无法获得堆栈跟踪.如果我的应用程序变得复杂,可能很难找到返回的代码块Error......根本原因是必不可少的.
那么我们在实践中做了什么?
我应该返回,而不是自定义Error,java类型Exception或Throwable我的Left?在不丢失堆栈跟踪和原因等重要信息的情况下,Scala异常处理的最佳实践是什么?
我有一个实例,Either[Future[A], Future[B]]我想将其转换为Future[Either[A, B]].
自从我上一个问题以来,已经发布了cat 0.8.1,改变了库的结构并Xor倾向于支持Either,这在2.12中是正确的.
因此,先前接受的答案中描述的方法不再起作用.我试图找到合适的进口但失败了.
cats.instances.either._
cats.implicits._
cats.syntax.bitraverse._
Run Code Online (Sandbox Code Playgroud)
看起来似乎有道理,但不幸的是不起作用.编译仍然失败value bisequence is not a member of Either[scala.concurrent.Future[A],scala.concurrent.Future[??B]]
扩展导入*.all._并没有改变编译器错误.
我在scala 2.11.8上,因为项目所依赖的所有库都没有发布2.12版本
either ×10
scala ×6
haskell ×3
java ×2
monads ×2
applicative ×1
exception ×1
for-loop ×1
functor ×1
java-8 ×1
performance ×1
scala-cats ×1
semigroup ×1