justanr / pynads

Dumb implementation of monads in Python.
MIT License
15 stars 3 forks source link

List behavior is inconsistent with Haskell. #4

Closed justanr closed 9 years ago

justanr commented 9 years ago

Consider building a chessboard through binds (example lifted from Dustin Getz's pymonads).

Adapting that code to pynads implementation should look like this:

from pynads import List

def chessboard(ranks, files):
    return List(*ranks) >> (lambda r:
           List(*files) >> (lambda f:
           List.unit((r,f))        ))

chessboard('abcedfgh', range(1,9))

Instead of getting List(('a', 1), ('a', 2), ...) we'll receive List('a', 1, 'a', 2, ...). This is in part to List.unit trying to be cute and convert iterables straight into a List monad rather than allowing a List monad containing an iterable. Where as with Haskell this results in [[1]]

test :: a -> [a]
test a = return a

test [1]

Moreover, simply removing the check on unit results in: List(<itertools.chain object at ...>)

Going further, and using the splat operator in List.bind results in this monster: List(List(List(('a',1)), List(('a',2)), ...), List(List(('b', 1)), ... ), ...)

Which is clearly not what's intended at all. Rather we're looking for: List(('a', 1), ('a', 2), ...).

I propose that pynads.List is fundamentally flawed and should be rewritten to mimic Haskell's behavior rather than attempting whatever it's doing now.