Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7779727
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T18:42:43+00:00 2026-06-01T18:42:43+00:00

I’m trying to compose seq-m and error-m to do list comprehensions on things that

  • 0

I’m trying to compose seq-m and error-m to do list comprehensions on things that can return errors. My output has unexpected types, though other than that it does actually seem to be sensible. i’ve exploded my code below, but here is a working gist as well.

here is my monadic business logic

def get_loan(name):
    m_qualified_amounts = (
           bind(get_banks(name), lambda bank:
           bind(get_accounts(bank, name), lambda account:
           bind(get_balance(bank, account), lambda balance:
           bind(get_qualified_amount(balance), lambda qualified_amount:
                    unit(qualified_amount))))))
    return m_qualified_amounts

names = ["Irek", "John", "Alex", "Fred"]
for name, loans in zip(names, map(get_loan, names)):
    print "%s: %s" % (name, loans)

output

Irek: [None, 'Insufficient funds for loan, current balance is 35000', None, 'Insufficient funds for loan, current balance is 70000', None, 'Unable to get balance due to technical issue for Wells Fargo: 3']
John: [None, 'Insufficient funds for loan, current balance is 140000']
Alex: [[245000], None, [280000], None]
Fred: (None, 'No bank associated with name Fred')

i expect to see lists of tuples – the list is the result of the list comprehension, and each item in the final list should be a value in error-monad (value, error tuple). Its exactly as if one-too-many levels of nesting were removed by seq_bind.

here is my definition of the monads, which if its not correct, its very close because both monads work in isolation, just not combined.

def success(val): return val, None
def error(why): return None, why
def get_value(m_val): return m_val[0]
def get_error(m_val): return m_val[1]

# error monad
def error_unit(x): return success(x)
def error_bind(mval, mf):
    assert isinstance(mval, tuple)
    error = get_error(mval)
    if error: return mval
    else: return mf(get_value(mval))

def flatten(listOfLists):
    "Flatten one level of nesting"
    return [x for sublist in listOfLists for x in sublist]    

# sequence monad
def seq_unit(x): return [x]
def seq_bind(mval, mf):
    assert isinstance(mval, list)
    return flatten(map(mf, mval))

# combined monad !!
def unit(x): return error_unit(seq_unit(x))
def bind(m_error_val, mf):  
    return error_bind(m_error_val, lambda m_seq_val: seq_bind(m_seq_val, mf))

monadic API

def get_banks(name):
    if name == "Irek": return success(["Bank of America", "Wells Fargo"])
    elif name == "John": return success(["PNC Bank"])
    elif name == "Alex": return success(["TD Bank"])
    else: return error("No bank associated with name %s" % name)

def get_accounts(bank, name):
    if   name == "Irek" and bank == "Bank of America": return success([1, 2])
    elif name == "Irek" and bank == "Wells Fargo": return success([3])
    elif name == "John" and bank == "PNC Bank": return success([4])
    elif name == "John" and bank == "Wells Fargo": return success([5, 6])
    elif name == "Alex" and bank == "TD Bank": return success([7, 8])
    else: return error("No account associated with (%s, %s)" % (bank, name))

def get_balance(bank, account):
    if bank == "Wells Fargo":
        return error("Unable to get balance due to technical issue for %s: %s" % (bank, account))
    else:
        return success([account * 35000])  #right around 200,000 depending on acct number

def get_qualified_amount(balance):
    if balance > 200000:
        return success([balance])
    else:
        return error("Insufficient funds for loan, current balance is %s" % balance)

also looking for ways to improve the code. tagged haskell and clojure because this is idiomatic in these languages, the python community isn’t interested in this.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-01T18:42:44+00:00Added an answer on June 1, 2026 at 6:42 pm

    Combining monads by stacking like this is, in Haskell, using Monad Transformers. Set aside Daniel Wagner’s point that ListT is not a monad for moment. You have two monads with types:

    1. List a which looks like [x,y,z]
    2. (Error e) a which looks x, None or None, err

    If you convert one to a monad transformer and combine them, there are two ways:

    1. (ErrorT e) List a which looks like [ (x,None), (y,None), (None, err) ]
    2. ListT (ErrorT e) a which looks like [x,y,z], None or None, [x,y,z]

    You wanted a list of pairs, so I expect you want the first form. But your simple test does not agree with this. Your unit does not return a list of pairs as in (1.) but a pair of the list and None which is (2.).

    So you either have things backwards or you have a more complicated monad in mind. I will try and modify your gist to look like (1.).

    I think this code might do what you want:

    def flatten(listOfLists):
        "Flatten one level of nesting"
        assert isinstance(listOfLists, list)
        if len(listOfLists) > 0:
            assert isinstance(listOfLists[0], list)
        return [x for sublist in listOfLists for x in sublist]
    
    # sequence monad
    def seq_unit(x): return [x]
    def seq_bind(mval, mf): return flatten(map(mf, mval))
    
    # Decompose ErrorT e m a
    def get_value(m_val): return m_val[0]
    def get_error(m_val): return m_val[1]
    
    # hard coded "(ErrorT e) List a" instance of throwError, note that seq_unit is hardcoded
    def error_throwError(err): return (None, err)
    def errorT_list_throwError(err): return seq_unit(error_throwError(err))
    
    # "(ErrorT e) List a" monad
    def error_unit(x): return (x,None)
    def errorT_list_unit(x): return seq_unit(error_unit(x))
    
    def error_bind(mval, mf):
        assert isinstance(mval, tuple)
        error = get_error(mval)
        if error:
            return error_throwError(error)
        else: 
            return mf(get_value(mval))
    
    # Cannot have multi-line lambda
    def errorT_list_bind_helper(mval, mf):
        assert isinstance(mval, tuple)
        error = get_error(mval)
        if error:
            return errorT_list_throwError(error)
        else: 
            return mf(get_value(mval))
    
    def errorT_list_bind(mval, mf): return seq_bind(mval, lambda v: errorT_list_bind_helper(v, mf))
    
    # combined monad !! (ErrorT e) List a
    unit = errorT_list_unit
    bind = errorT_list_bind
    throwError = errorT_list_throwError
    
    # hard coded "lift :: List a -> (ErrorT e) List a"
    def lift(mval):
        assert isinstance(mval, list)
        # return [ (val,None) for val in mval ]
        # return [ errorT_list_unit(val) for val in mval ]
        return seq_bind(mval, lambda v : unit(v))
    
    def get_banks(name):
        if name == "Irek": return lift(["Bank of America", "Wells Fargo"])
        elif name == "John": return unit("PNC Bank")
        elif name == "Alex": return unit("TD Bank")
        else: return throwError("No bank associated with name %s" % name)
    
    def get_accounts(bank, name):
        if   name == "Irek" and bank == "Bank of America": return lift([1, 2])
        elif name == "Irek" and bank == "Wells Fargo": return unit(3)
        elif name == "John" and bank == "PNC Bank": return unit(4)
        elif name == "John" and bank == "Wells Fargo": return lift([5, 6])
        elif name == "Alex" and bank == "TD Bank": return lift([7, 8])
        else: return throwError("No account associated with (%s, %s)" % (bank, name))
    
    def get_balance(bank, account):
        if bank == "Wells Fargo":
            return throwError("Unable to get balance due to technical issue for %s: %s" % (bank, account))
        else:
            return unit(account * 35000)  #right around 200,000 depending on acct number
    
    def get_qualified_amount(balance):
        if balance > 200000:
            return unit(balance)
        else:
            return throwError("Insufficient funds for loan, current balance is %s" % balance)
    
    # monadic business logic
    def get_loan(name):
    
        m_qualified_amounts = (
               bind(get_banks(name), lambda bank:
               bind(get_accounts(bank, name), lambda account:
               bind(get_balance(bank, account), lambda balance:
               bind(get_qualified_amount(balance), lambda qualified_amount:
                        unit(qualified_amount))))))
    
        assert isinstance(m_qualified_amounts, list)
        assert isinstance(m_qualified_amounts[0], tuple)
        return m_qualified_amounts
    
    names = ["Irek", "John", "Alex", "Fred"]
    
    for name, loans in zip(names, map(get_loan, names)):
        print "%s: %s" % (name, loans)
    

    Output is

    Irek: [(None, 'Insufficient funds for loan, current balance is 35000'), (None, 'Insufficient funds for loan, current balance is 70000'), (None, 'Unable to get balance due to technical issue for Wells Fargo: 3')]
    John: [(None, 'Insufficient funds for loan, current balance is 140000')]
    Alex: [(245000, None), (280000, None)]
    Fred: [(None, 'No bank associated with name Fred')]
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
Basically, what I'm trying to create is a page of div tags, each has
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I've got a string that has curly quotes in it. I'd like to replace
I'm trying to create an if statement in PHP that prevents a single post
I am trying to understand how to use SyndicationItem to display feed which is
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I want to count how many characters a certain string has in PHP, but
I have a string like this: La Torre Eiffel paragonata all’Everest What PHP function

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.