3 ms·
That's like saying arithmetic doesn't work in dynamic languages because nothing stops you from writing (+ 42 "foo"). Sure, you won't get a compiler error - tha
by mbrubeck 17y ago
That's like saying arithmetic doesn't work in dynamic languages because nothing stops you from writing (+ 42 "foo"). Sure, you won't get a compiler error - that's why it's a dynamic language! - but you will get an error at runtime. What "stops" you from writing broken code are automated tests, lint checkers, discipline, and common sense.
I say this as someone who has implemented monadic code in both JavaScript and Haskell, including a small homegrown parser combinator module: http://limpet.net/mbrubeck/2009/10/30/compleat.html http://limpet.net/mbrubeck/2009/10/30/compleat.html
- eru 17y agoSo as a summary: In dynamic languages the compiler does not enforce the monad laws. I add: They aren't enforced completely in Haskell, either. (And you can't even express every monad in Haskell. E.g. you can't even make Set a functor in Haskell.)
- jrockway 17y agoyou can't even make Set a functor in Haskell Well sure, because map on a set is only defined over functions that return values that can be compared for equality, whereas the generic functor map is defined over all functions.
- eru 17y agoExactly. (However Data.Set is only defined for comparable values, i.e. the Ord typeclass, not Eq.)
- jrockway 17y agoBut that's not what monads are, what you have without a type system is just "calling a function with the result of another function". You could use the function composition operator to the same effect. Having also implemented a monad library in a dynamically-typed language, I am well aware of what happens when one operand of bind returns the wrong type. The rest of the computation silently proceeds with that type, until it happens to change again. This results in a subtle loss of information, rather than outright failure. Like I said, programming with combinators is a great way to reuse code -- but not all combinators that are of type "f a -> (a -> g b) -> g b" are monadic. It's only a monad when f = g.
- stevenashley 17y agoThere is nothing to stop one from using reflection to ensure the types are correct at runtime...
- mbrubeck 17y agoI totally agree that you loose static safety guarantees when you program in a dynamically-typed language. But the lack of compiler support does not prevent you from writing code that is monadic (both in its types, and in the other monad laws - which another commenter mentioned are not provable by most statically-typed languages either). You seem to agree with this, since you say you've implemented monadic functions in a dynamic language. Really you are just saying that it requires other sources of discipline, which is true of lots of things besides monads. For example, I see you are a Perl hacker. In Perl, even my simple (42 + "foo") example results in "subtle loss of information." This doesn't mean that + doesn't work in Perl, just that someone other than the compiler has to make sure the values on either side have compatible types. Look at the clojure.contrib.monad documentation, and you'll see that monads do have benefits beyond "normal" combinators, even if those benefits don't include all the static safety of Haskell or ML. You get the "domonad" macro which provides the same benefits as Haskell's "do" syntactic sugar. You get generic lifting/mapping/chaining functions that you can use with any monad (like the Control.Monad module in Haskell), and you can write similar generic functions of your own: http://richhickey.github.com/clojure-contrib/monads-api.html http://richhickey.github.com/clojure-contrib/monads-api.html Generic/parametric monad actions do look different in a language with a weak type system. Rather than letting type inference take care of polymorphism for you, you have to use other language features. For example, in JavaScript you can use objects and duck-typing, letting the function access the enclosing monad's operations through an implicit object parameter. I don't know enough Clojure yet to know the equivalent idiom.