在Python中,为什么不使用另一个“bind”方法而不是一个适用于“bind”的函子呢;“无短路”;输入验证?

在Python中,为什么不使用另一个“bind”方法而不是一个适用于“bind”的函子呢;“无短路”;输入验证?,python,functional-programming,applicative,Python,Functional Programming,Applicative,我一直在探索如何在Python中从头开始使用monad/ApplicationFunctor进行数据验证 特别是,我创建了一个新的验证类,它允许表示验证的结果:成功和错误。它基本上是一个标称的结果类型,但不完全是: from\uuuuu future\uuuuu导入注释 从输入导入列表、TypeVar、Generic、Callable、Optional A=TypeVar('A') B=TypeVar('B') 类验证(通用[A]): def uuu init uuu(self,value:Op

我一直在探索如何在Python中从头开始使用monad/ApplicationFunctor进行数据验证

特别是,我创建了一个新的
验证
类,它允许表示验证的结果:
成功
错误
。它基本上是一个标称的
结果
类型,但不完全是:

from\uuuuu future\uuuuu导入注释
从输入导入列表、TypeVar、Generic、Callable、Optional
A=TypeVar('A')
B=TypeVar('B')
类验证(通用[A]):
def uuu init uuu(self,value:Optional[A],errors:List[str])->None:
自我价值=价值
self.errors=错误
def代表成功(自我):
引发未实现错误(“”)
def是_错误(自身):
返回非自我。是否成功()
def映射(自身,函数:可调用[[A],B])->验证[B]:
引发未实现错误(“”)
def绑定(self,function:Callable[[A],Validation[B]])->Validation[B]:
引发未实现错误(“”)
类错误(验证[A]):
定义初始化(self,错误:List[str])->无:
super()。\uuuu init\uuuu(无,错误)
def代表成功(自我):
返回错误
def映射(自身,函数:可调用[[A],B])->验证[B]:
回归自我
def绑定(self,function:Callable[[A],Validation[B]])->Validation[B]:
回归自我
课堂成功(验证[A]):
def uuu init uuu(self,value:A)->无:
超级()
def代表成功(自我):
返回真值
def映射(自身,函数:可调用[[A],B])->验证[B]:
返回函数(self.value)
def绑定(self,function:Callable[[A],Validation[B]])->Validation[B]:
返回函数(self.value)
这工作正常,在遇到第一个错误时将停止:

def check_1(数据:str)->验证[str]:
打印(f“数据1:{data}”)
返回成功(数据)
def check_2(数据:str)->验证[str]:
打印(f“数据2:{data}”)
返回错误(['无法通过检查2'进行验证])
def check_3(数据:str)->验证[str]:
打印(f“数据3:{data}”)
返回错误(['无法通过检查3'进行验证])
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“在第一个错误时停止(又名monad的绑定):”)
检查=成功('检查输入')\
.bind(勾选1)\
.bind(勾选2)\
.bind(勾选3)
assert checks.value为无
断言检查。错误==['无法使用检查2进行验证']
为什么要这样定义
bind

没有什么能阻止我定义新的
bind2
,它不会在遇到第一个错误时停止,而是会尝试所有错误,直到结束:

类验证(通用[A]): # (...) def bind2(self,function:Callable[[A],Validation[B]])->Validation[B]: 引发未实现错误(“”) 类错误(验证[A]): # (...) def bind2(self,function:Callable[[A],Validation[B]])->Validation[B]: 回归自我 课堂成功(验证[A]): # (...) def bind2(self,function:Callable[[A],Validation[B]])->Validation[B]: 应用=功能(自我价值) if application.is_success(): 退货申请 其他: self.errors+=application.errors 回归自我 这与预期的一样有效:

如果名称=“\uuuuu main\uuuuuuuu”:
打印(“显示所有错误,但不在第一个错误处停止:”)
检查=成功('检查输入')\
.bind2(勾选1)\
.bind2(勾选2)\
.bind2(勾选3)
assert checks.value==“要检查的输入”
断言检查。错误==['无法使用检查2进行验证','无法使用检查3进行验证']
既然如此,为什么不让
bind2
不短路呢

我已经读到这里应该使用applicative functors的
apply
方法,但我并不认为这有什么帮助,因为它的签名是
def apply(self,function:Validation[Callable[[A],B]])->Validation[B]:
(如果我没弄错的话)它不接受我的任何
check_x
函数签名