Python中的monad错误 - 我做得对吗?

时间:2012-04-04 01:36:33

标签: python monads

问题:

  • 这是一个单子吗?
  • 这是否证明了对错误monad的合理理解?
  • 我错过了什么?
  • 我还能用这个代码做更多的flex monad吗?
  • 我对成功/失败与“返回”/“结果”/“提升”的关系感到困惑(我认为这些都是相同的概念)。
  • 我们怎样才能使问题更复杂,以便monads帮助我们解决我们的痛点? monads在这里提供帮助,因为我们抽象了if result != None管道,我想抽象出其他类型的管道,monad(或'monad combinators')如何帮助这种痛苦?

我有点不知所措。

# helpers for returning error codes
def success(x): return (True, x)
def fail(x): return (False, x)

# bind knows how to unwrap the return value and pass it to
# the next function
def bind(mv, mf):
    succeeded = mv[0]
    value = mv[1]

    if (succeeded): return mf(value)
    else: return mv

def lift(val): return success(val)

def userid_from_name(person_name):
    if person_name == "Irek": return success(1)
    elif person_name == "John": return success(2)
    elif person_name == "Alex": return success(3)
    elif person_name == "Nick": return success(1)
    else: return fail("No account associated with name '%s'" % person_name)

def balance_from_userid(userid):
    if userid == 1: return success(1000000)
    elif userid == 2: return success(75000)
    else: return fail("No balance associated with account #%s" % userid)

def balance_qualifies_for_loan(balance):
    if balance > 200000: return success(balance)
    else: return fail("Insufficient funds for loan, current balance is %s" % balance)

def name_qualifies_for_loan(person_name):
    "note pattern of lift-bind-bind-bind, we can abstract further with macros"
    mName =    lift(person_name)
    mUserid =  bind(mName, userid_from_name)
    mBalance = bind(mUserid, balance_from_userid)
    mLoan =    bind(mBalance, balance_qualifies_for_loan)

    return mLoan

for person_name in ["Irek", "John", "Alex", "Nick", "Fake"]:
    qualified = name_qualifies_for_loan(person_name)
    print "%s: %s" % (person_name, qualified)

输出:

Irek: (True, 1000000)
John: (False, 'Insufficient funds for loan, current balance is 75000')
Alex: (False, 'No balance associated with account #3')
Nick: (True, 1000000)
Fake: (False, "No account associated with name 'Fake'")

1 个答案:

答案 0 :(得分:2)

这是monad吗?请参阅monad laws

  

Monad课程的所有实例都应遵守:

     
      
  1. “左侧身份”:   返回>> =f≡fa
  2.   
  3. “正确的身份”:   m>> =返回≡m
  4.   
  5. “关联性”:   (m>> = f)>> =g≡m>> =(\ x - > f x>> = g)
  6.   

return表示成功,>>=表示绑定)

  1. 左侧身份。在您的实现中,这可能是:

    bind(success(x), balance_qualifies_for_loan) == balance_qualifies_for_loan(x) 
    

    其中x是某个值,f是一个monadic函数。

  2. 正确的身份。同样,这可能是:

    bind(m, success) == m
    

    其中m是monadic值。

  3. 关联性。这可能是:

    bind(bind(m,  userid_from_name), balance_from_userid)) ==
      bind(m, lambda x: bind(userid_from_name(x), balance_from_userid))
    
  4. 所有这些都可以写成单元测试,以快速检查这些属性是否适用于许多输入值。

    缺少什么?

    • 每个monad都需要successbind的不同实现。将这些放入接口将允许您在所有已实现的monad上编写通用代码。
    • 基于the Haskell approach,您可能希望实现一些常规monad组合器,例如>>sequencemapM。这些使monad非常方便使用。