Is there a Python equivalent for Scala's Option or Either?

前端 未结 8 1551
忘掉有多难
忘掉有多难 2021-02-05 01:26

I really enjoy using the Option and Either monads in Scala. Are there any equivalent for these things in Python? If there aren\'t, then what is the pythonic way of handling erro

相关标签:
8条回答
  • 2021-02-05 01:49

    Try This:

    from monad import Monad
    
    class Either(Monad):
      # pure :: a -> Either a
      @staticmethod
      def pure(value):
        return Right(value)
    
      # flat_map :: # Either a -> (a -> Either b) -> Either b
      def flat_map(self, f):
        if self.is_left:
          return self
        else:
          return f(self.value)
    
    class Left(Either):
      def __init__(self, value):
        self.value = value
        self.is_left = True
    
    class Right(Either):
      def __init__(self, value):
        self.value = value
    self.is_left = False
    
    0 讨论(0)
  • 2021-02-05 01:51

    I realize this is pretty late to the party but I came to this page on top of google before deciding to implement it so maybe I can help others googling with this. I implemented it, you can get it from pypi as pyther-maybe, it implements both Either and Maybe with Maybe as a special subclass of Either. This example should explain how it works:

    import sys
    from pyther_maybe import *
    
    def save_div ( x, y ):
        if y == 0:
            return nothing() # alias of Maybe()
        else:
            return value(x / y) # alias of Maybe(x / y)
    
    float_test = save_div(1.0, 3.0)
    
    assert isinstance(float_test, Maybe)
    
    if float_test: #nothing tests as false:
        float = float_test() # calling the container with no arguments returns its value
    else:
        sys.exit("something went wrong")
    
    print float
    
    # or if you want to encode a reason:
    
    def save_div ( x, y ):
        if y == 0:
            return left("You can't divide by zero, silly") # alias of Either(left=...)
        else:
            return right(x / y) # alis of Either(...)
    
    float_test = save_div(4.2, 0.0)
    
    assert isinstance(float_test, Either)
    
    def fake_exit ( string ):
        print "We would have exited with:"
        print string
        return "Whatever value"
    
    if float_test:
        # these two are te same
        float = float_test()
        float = float_test.right()
    else:
        fake_exit(float_test.left())
    
    # or in a shorter and more pleasant format
    # does the same as above
    float = float_test.extract(fake_exit)
    
    print float # prints "Whatever value"
    
    # Also, these containers are mutable:
    
    box = nothing()
    
    try:
        print box() # raises exception
    except RightEitherException:
        print "We caught an exception"
    
    def change_box():
        box(4)
    
    change_box()
    print box() # 4
    

    It has more features than that, some of which are pretty useless in practise (it's also an iterator for instance and has subscript notation like pyther_maybe.either(x)[pyther_maybe.Right] == x.

    0 讨论(0)
提交回复
热议问题