标签: either

在左边的映射

在我的应用程序的某个地方,我Either ParserError MyParseResult从Parsec 收到一个.在下游,这个结果可以使用其他库完成其他一些解析.在第二阶段的解析过程中,也可能会出现某种错误,我希望将其作为a传递Left String,但为此我需要将结果从Parsec转换为String.为了实现这一点,我需要一个允许我Left使用show函数映射a 的函数.

我想的映射函数看起来像这样:

mapLeft :: (a -> b) -> Either a c -> Either b c
mapLeft f (Left x) = Left $ f x
mapLeft _ x = x
Run Code Online (Sandbox Code Playgroud)

但我很惊讶没有发现任何与hackage db相匹配的东西.所以现在我怀疑我是否正在使用正确的方法解决我的问题.

为什么标准库中没有这样的功能?我的做法有什么问题?

haskell either

20
推荐指数
3
解决办法
4200
查看次数

获得任何一个的价值

除了使用之外match,是否有类似于选项的方式来getOrElse实现Right或者Left值的实际内容?

scala> val x: Either[String,Int] = Right(5)
scala> val a: String = x match { 
                                case Right(x) => x.toString
                                case Left(x) => "left" 
                       }
a: String = 5
Run Code Online (Sandbox Code Playgroud)

scala either

19
推荐指数
2
解决办法
2万
查看次数

验证与分离

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

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
查看次数

如何拆分列表[[A,B]]

我想拆分List[Either[A, B]]两个列表.

有没有更好的办法 ?

def lefts[A, B](eithers : List[Either[A, B]]) : List[A] = eithers.collect { case Left(l) => l}
def rights[A, B](eithers : List[Either[A, B]]) : List[B] = eithers.collect { case Right(r) => r}
Run Code Online (Sandbox Code Playgroud)

scala either

19
推荐指数
5
解决办法
6195
查看次数

我如何处理返回的任何一个

如果是scala函数

def A(): Either[Exception, ArrayBuffer[Int]] = {
...
}
Run Code Online (Sandbox Code Playgroud)

什么应该是处理返回结果的正确方法? val a = A() 和?

scala either

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

如何从 Dart (Dartz) 中的任一种类型中轻松提取左或右

我希望从返回类型的方法中轻松提取值Either<Exception, Object>

我正在做一些测试,但无法轻松测试我的方法的返回。

例如:

final Either<ServerException, TokenModel> result = await repository.getToken(...);
Run Code Online (Sandbox Code Playgroud)

为了测试我能够做到这一点

expect(result, equals(Right(tokenModelExpected))); // => OK
Run Code Online (Sandbox Code Playgroud)

现在如何直接检索结果?

final TokenModel modelRetrieved = Left(result); ==> Not working..
Run Code Online (Sandbox Code Playgroud)

我发现我必须这样投:

final TokenModel modelRetrieved = (result as Left).value; ==> But I have some linter complain, that telling me that I shouldn't do as to cast on object...
Run Code Online (Sandbox Code Playgroud)

我也想测试异常但它不起作用,例如:

expect(result, equals(Left(ServerException()))); // => KO
Run Code Online (Sandbox Code Playgroud)

所以我试过这个

expect(Left(ServerException()), equals(Left(ServerException()))); // => KO as well, because it says that the instances are different.
Run Code Online (Sandbox Code Playgroud)

unit-testing either dart flutter

17
推荐指数
2
解决办法
1万
查看次数

是否没有标准(A a a)monad实例?

我的印象是,某个地方有一个实例,但我似乎无法找到它.我已经尝试导入Control.Monad,Control.Monad.Instances和Data.Either,如图所示

module Main where

import Control.Monad
import Data.Either
import Control.Monad.Instances

test :: [Either a b] -> Either a [b]
test = sequence

main = return ()
Run Code Online (Sandbox Code Playgroud)

但ghc告诉我它无法演绎(Monad(Either a)).添加

instance Monad (Either a) where
    return = Right
    Right b >>= f = f b
    Left a >>= _ = Left a
Run Code Online (Sandbox Code Playgroud)

使代码编译,但是这个实例声明似乎很普遍,如果它在某些标准模块中还没有出现,那对我来说没有意义.如果是的话,我应该在哪里找到它,如果不是,那么有没有理由呢?

--------------编辑---------------

请注意,我现在认为下面的user31708的答案("从4.6开始,实例在Data.Either本身.")是目前正确的答案.我不确定在这种情况下重新分配所选答案的正确协议,其中所选答案是在提出问题时的正确答案,所以我保持原样.如果还有其他指导方针,请纠正我.

import monads haskell instance either

16
推荐指数
3
解决办法
5226
查看次数

尝试[结果],IO [结果],[错误,结果],我应该在最后使用

我想知道我的方法应该是什么签名,以便我优雅地处理不同类型的失败.

这个问题在某种程度上是我已经在Scala中处理错误的许多问题的总结.你可以在这里找到一些问题:


现在,我理解以下内容:

  • 两者都可以用作可能失败的方法调用的结果包装器
  • 尝试是一个正确的biaised要么失败是一个非致命的例外
  • IO(scalaz)有助于构建处理IO操作的纯方法
  • 所有3个都很容易用于理解
  • 由于不兼容的flatMap方法,所有3个都不容易混合以便理解
  • 在功能性语言中,除非它们是致命的,否则我们通常不会抛出异常
  • 我们应该为真正特殊情况抛出异常.我想这是尝试的方法
  • 创建Throwables具有JVM的性能成本,并不适用于业务流程控制

存储库层

现在请考虑我有一个UserRepository.所述UserRepository存储的用户,并限定了findById方法.可能发生以下故障:

  • 致命的失败(OutOfMemoryError)
  • IO失败,因为数据库不可访问/可读

此外,用户可能会丢失,从而导致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 either scalaz

15
推荐指数
2
解决办法
2519
查看次数

为什么我们需要Monad而不是Monad

我正在玩Maybe和Either monad类型(链接,根据返回值应用条件函数,还返回链接函数失败的错误消息等).所以我觉得我们可以通过使用Either monad来实现相同和更多的事情.那么我的问题是那些之间的实际或概念上的区别?

monads haskell functional-programming either maybe

15
推荐指数
2
解决办法
1109
查看次数

为什么`Left` 和`Right` 有两个类型参数?

我知道现在很难在不破坏现有代码的情况下进行更改,但我想知道为什么首先要这样做。

为什么不只是:

sealed trait Either[+A, +B]
case class Left[A](x: A) extends Either[A, Nothing]
case class Right[B](x: B) extends Either[Nothing, B]
Run Code Online (Sandbox Code Playgroud)

这里是否有一些我没有看到的缺点......?

scala either

13
推荐指数
2
解决办法
1469
查看次数