说我有以下功能:
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.你显然需要类型别名才能工作,这就是我重新定义的原因 …
我有一个表示算术运算符的和类型:
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)