热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

嵌套的Eithers具有不同的错误类型

如何解决《嵌套的Eithers具有不同的错误类型》经验,为你挑选了1个好方法。

我有一个嵌套有不同的错误类型,看起来像:

Either e1 (Either e2 a)

我想要一个像以下一样的函数:

Either e1 (Either e2 a) -> Either e2 a

更一般地说,是否存在匹配此模式的类型类?



1> Alexis King..:
你的功能是不可能的!

你所要求的并不是真正有意义的.我们来看看你的函数类型:

f :: Either e1 (Either e2 a) -> Either e2 a

假设这个函数是完全的(因为Haskell中绝大多数函数应该是真的应该),我们需要Either e2 a任何类型的输入生成一个类型的值Either e1 (Either e2 a).为了尝试实现这一点,让我们考虑输入可以带来的所有"形状".

事实证明,该类型的值Either e1 (Either e2 a)可以有三种可能的形状:

Left _
Right (Left _)
Right (Right _)

底部两个形状易于处理.实际上,我们可以将任何Right值映射到自身:

f (Right x) = x

但是,这不处理Left外壳.我们可以从编写模式开始:

f (Left x) = ???

在上面的模式中,我们得到一个x带有类型的值e1.我们需要生成一个类型的值Either e2 a.这意味着我们基本上需要一个具有以下类型的函数:

g :: e1 -> Either e2 a

可是等等!这种类型显然不可能满足,因为我们需要一个e2或一个a,但我们所拥有的只是一个e1.因此,我们无法实现这种情况(假设我们没有无限循环或使用errorundefined).我们被困住了.

解决方案1:提供更多信息

在不知道你真正想做什么的情况下,很难为这个问题提供一个好的解决方案.我至少可以提供一些可能性,其中一个可能与您的用例相关.

一个简单的解决方案是提供一种映射e1值的方法e2.这样,我们可以将所有错误归一化为e2.在either函数的帮助下实现这一点非常简单:

f :: (e1 -> e2) -> Either e1 (Either e2 a) -> Either e2 a
f g = either (Left . g) id

您也可以通过将映射函数应用于外部的左侧Either,然后使用monadic join函数合并两个层来完成此操作:

import Data.Bifunctor

f :: (e1 -> e2) -> Either e1 (Either e2 a) -> Either e2 a
f g = join . first g
解决方案2:更改结果类型

我们可以处理这个问题的另一种方法是调整结果以编码两种可能性.我们可以生成一个类型的值Either (Either e1 e2) a来保存可能的错误.使用该either函数编写它也相当容易:

f :: Either e1 (Either e2 a) -> Either (Either e1 e2) a
f = either (Left . Left) (either (Left . Right) Right)

但是,使用模式匹配可能更清晰,而不是either:

f :: Either e1 (Either e2 a) -> Either (Either e1 e2) a
f (Left x) = Left (Left x)
f (Right (Left x)) = Left (Right x)
f (Right (Right x)) = Right x


推荐阅读
author-avatar
手浪用户2602898067
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有