小编blo*_*rat的帖子

在EitherT和验证之间切换以累积错误或遍历

说我有以下功能:

def getRemoteThingy(id: Id): EitherT[Future, NonEmptyList[Error], Thingy]
Run Code Online (Sandbox Code Playgroud)

鉴于a List[Id],我可以轻松地List[Thingy]使用Traverse[List]以下方法检索:

val thingies: EitherT[Future, NonEmptyList[Error], List[Thingy]] = 
  ids.traverseU(getRemoteThingy)
Run Code Online (Sandbox Code Playgroud)

它将使用将基于的Applicative实例,因此我将只获取第一个,它不会附加所有这些实例.那是对的吗?EitherTflatMapNonEmptyList[Error]

现在,如果我真的想积累错误,我可以在EitherT和之间切换Validation.例如:

def thingies2: EitherT[Future, NonEmptyList[Error], List[Thingy]] = 
  EitherT(ids.traverseU(id => getRemoteThingy(id).validation).map(_.sequenceU.disjunction))
Run Code Online (Sandbox Code Playgroud)

它有效,我最后得到了所有的错误,但它非常麻烦.我可以通过使用组合使其更简单Applicative:

type ValidationNelError[A] = Validation[NonEmptyList[Error], A]
type FutureValidationNelError[A] = Future[ValidationNelError[A]]
implicit val App: Applicative[FutureValidationNelError] =
  Applicative[Future].compose[ValidationNelError]

def thingies3: EitherT[Future, NonEmptyList[Error], List[Thingy]] = 
  EitherT(
    ids.traverse[FutureValidationNelError, Thingy](id => 
      getRemoteThingy(id).validation
    ).map(_.disjunction)
  )
Run Code Online (Sandbox Code Playgroud)

比其他人更长,但所有管道都可以在代码库中轻松共享.

您如何看待我的解决方案?有没有更优雅的方法来解决这个问题?你通常如何处理它?

非常感谢你.

编辑:

我有一种疯狂的解决方案,使用自然变换皮条客Traversable.你显然需要类型别名才能工作,这就是我重新定义的原因 …

scala monad-transformers scalaz scalaz7

6
推荐指数
0
解决办法
571
查看次数

在Idris中列出和类型元素的惯用法

我有一个表示算术运算符的和类型:

data Operator = Add | Substract | Multiply | Divide
Run Code Online (Sandbox Code Playgroud)

我正在尝试为它编写解析器.为此,我需要一份详尽的所有运营商名单.

在Haskell中,我将使用deriving (Enum, Bounded)以下StackOverflow问题中的建议:获取Haskell中所有可能的数据类型值的列表

不幸的是,问题#19所建议的伊德里斯似乎没有这样的机制.大卫·克里斯蒂安森正在就这个问题进行一些正在进行的工作,所以希望将来情况会有所改善:david-christiansen/derive-all-the-instances

来自Scala,我习惯手动列出元素,所以我很自然地想出了以下内容:

Operators : Vect 4 Operator
Operators = [Add, Substract, Multiply, Divide]
Run Code Online (Sandbox Code Playgroud)

为了确保Operators包含所有元素,我添加了以下证明:

total
opInOps : Elem op Operators
opInOps {op = Add} = Here
opInOps {op = Substract} = There Here
opInOps {op = Multiply} = There (There Here)
opInOps {op = Divide} = There (There (There Here))
Run Code Online (Sandbox Code Playgroud)

因此,如果我在Operator不添加元素的情况下添加元素Operators,则整体检查器会抱怨:

Parsers.opInOps is …
Run Code Online (Sandbox Code Playgroud)

dependent-type idris

6
推荐指数
1
解决办法
202
查看次数