10

I am trying to understand maybe Monad but most of the examples I saw used some language-specific feature. To ensure that I have gotten it conceptually right I thought of writing a generic implementation. Below is what I came up with.

Can someone tell if I have gotten it conceptually right? Is there a better way to generalize it?

def f():
    return 2

def g():
    return 4

def h():
    return 7

def i():
    return None

def bind(val, func):
    if val is None:
        return None
    else:
        return(func())

unit = 0

>>> bind(bind(bind(unit,f),i),h) #Returns nothing
>>> bind(bind(bind(unit,f),g),h) #Returns a value
>>>7 

What if I wanted to add the values from these functions and abort if any of those was NULL; any suggestion?

Dev Maha
  • 1,133
  • 1
  • 11
  • 24
  • Could be relevant: http://stackoverflow.com/questions/8507200/maybe-kind-of-monad-in-python – Yuras Jul 25 '13 at 18:43
  • 17
    @Joehillen that's not at all true. Monads can indeed be quite useful in dynamically typed languages. – Matt Fenwick Jul 25 '13 at 18:59
  • @Matt Fenwick How? There aren't any types. What are you wrapping in the monad? – Joe Hillenbrand Jul 25 '13 at 19:56
  • 7
    @Joehillen: dynamically typed languages do have types. What do you think the `type` function does? – Ben Millwood Jul 25 '13 at 21:16
  • 3
    @Joehillen Dynamic/static typing and strong/weak typing are independent of each other. You can have a strongly and dynamically typed language; Python and Ruby are both good examples. –  Jul 26 '13 at 06:27

1 Answers1

9

You're very close, but the signature of bind is

m a -> (a -> m b) -> m b

So it's "unwrapping" m and passing the contained value to the next function. You currently have

m a -> ( () -> m b) -> m b

Since you're just ignoring the val bind gets, you should have

def bind(val, func):
    if val is None:
        return None
    else:
        return(func(val))

This is equivalent to >>= in Haskell. What you had before was >> which should be implemented as

# "ignore" bind
def ibind(val, func):
    bind(val, lambda _ : func())

which just happily throws away the value bind passes it.

To take this further, you'd have to introduce a class

class Maybe():
    def __init__(v):
        self.val = v
        self.isNothing = False
Nothing = Maybe(None)
Nothing.isNothing = True

def bind(val, func):
    if val.isNothing:
        return Nothing
    else:
        return(func(val.val))
daniel gratzer
  • 52,833
  • 11
  • 94
  • 134
  • 1
    How would you distinguish between `Nothing` and `Just Nothing`? – Joe Hillenbrand Jul 25 '13 at 18:46
  • 2
    @Joehillen You can't, but as a conceptual example for understanding monads I think this is fine – daniel gratzer Jul 25 '13 at 18:48
  • @jozefg thank you so much for replying. I knew the general signature of bind but my confusion was (and still is) that my functions (f, g and others) don't take any input parameter so I can't do func(val), what do I do then? – Dev Maha Jul 25 '13 at 21:45
  • 2
    @DevMaha Change your functions, so that they do take a parameter or use your functions with `ibind` rather than `bind`. – sepp2k Jul 25 '13 at 21:47