Live data from Hacker News

"Welcome to the Machine": State monads in Clojure

brehaut.net

11–18 of 18 posts

Re: "Welcome to the Machine": State monads in Clojure

#11
post #7

Earlier quoted context omitted.

I 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 i…

For example, I see you are a Perl hacker. In Perl, even my simple (42 + "foo") example results in "subtle loss of information." Sure, but I don't call "+" addition, it's just Perl's "plus operator" which happens to be defined over numbers and strings. Personally, I don't see why every language is trying to copy Haskell's monads. A monad is not some deeply important concept, it's just an abstraction that happened to b…

"Without Haskell's type system, it is not quite as useful, and it's possible that other abstractions would be better."

Sure! I'd be happy to agree with this statement.

Re: "Welcome to the Machine": State monads in Clojure

#12
post #7

Earlier quoted context omitted.

I 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 i…

For example, I see you are a Perl hacker. In Perl, even my simple (42 + "foo") example results in "subtle loss of information." Sure, but I don't call "+" addition, it's just Perl's "plus operator" which happens to be defined over numbers and strings. Personally, I don't see why every language is trying to copy Haskell's monads. A monad is not some deeply important concept, it's just an abstraction that happened to b…

I prefer to disagree. Monads are an important concept [1], that crop up in a lot of different places. (Or express differently: That help to better organize your code in a lot of situations.)

Functors and pointed functors and arrows are also quite important.

[1] Though not the most important one.

Re: "Welcome to the Machine": State monads in Clojure

#13
post #8
post #5

Earlier quoted context omitted.

But 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, un…

"...without a type system..." Sorry to be a pedant, but dynamically typed is not the same as without a type system, it is merely without a type checker. They probably look the same to somebody well versed in Haskell but the distinction matters.

As somebody well-versed in Haskell, I can attest that a dynamic type system does look different to me than no type system.

With a dynamic type system you get your errors at least at runtime. With no type system your program just behaves wrong.

Re: "Welcome to the Machine": State monads in Clojure

#14
post #9
post #4

Earlier quoted context omitted.

So 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.)

you 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.

Exactly. (However Data.Set is only defined for comparable values, i.e. the Ord typeclass, not Eq.)

Re: "Welcome to the Machine": State monads in Clojure

#15
post #14
post #9

Earlier quoted context omitted.

you 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.

Exactly. (However Data.Set is only defined for comparable values, i.e. the Ord typeclass, not Eq.)

That is an efficiency hack to make it O(n log n) instead of O(n^2) rather than an intrinsic property of sets, functors, or Haskell :)

Re: "Welcome to the Machine": State monads in Clojure

#16
post #14

Earlier quoted context omitted.

Exactly. (However Data.Set is only defined for comparable values, i.e. the Ord typeclass, not Eq.)

That is an efficiency hack to make it O(n log n) instead of O(n^2) rather than an intrinsic property of sets, functors, or Haskell :)

Indeed. But Hindley-Milner [1] type systems have trouble expressing commutative stuff in general.

[1] I hope I got the names correct.

Re: "Welcome to the Machine": State monads in Clojure

#17
post #2

I don't think monads really work in dynamically typed languages, because there is no way for the bind combinator to ensure that both operands return the same type. Consider: f :: Int -> Either String Int f 0 = Left "Zero is not allowed!" f x = x + 42 g :: Int -> [Int] g x | x > 1 = [1..x] (These are functions of one argument that return an Int in a monad; Either and [] are the monads. The Error monad will bind the "R…

If I remember correctly, there was a more tricky problem in implementing monads without the type system - sometimes which monad is chosen for an expression, depends not just on the arguments, but the expected type of the result. Ex : "return 3" might be [3] or an IO action with result 3. The compiler decides this based on the surrounding context. In dynamical languages one would have to manually specify which kind of 'return' you mean.

This surrounding context inference feature, which is useful for type classes other than monads, has the unusual consequence that you need to specify more typeinfo in a dynamic language.

Re: "Welcome to the Machine": State monads in Clojure

#18
post #2

I don't think monads really work in dynamically typed languages, because there is no way for the bind combinator to ensure that both operands return the same type. Consider: f :: Int -> Either String Int f 0 = Left "Zero is not allowed!" f x = x + 42 g :: Int -> [Int] g x | x > 1 = [1..x] (These are functions of one argument that return an Int in a monad; Either and [] are the monads. The Error monad will bind the "R…

If I remember correctly, there was a more tricky problem in implementing monads without the type system - sometimes which monad is chosen for an expression, depends not just on the arguments, but the expected type of the result. Ex : "return 3" might be [3] or an IO action with result 3. The compiler decides this based on the surrounding context. In dynamical languages one would have to manually specify which kind of…

Clojure (being a lisp) uses macros and some dynamic variables to manage this sort of polymorphism. The clojure library provides a defmonad macro to let you define the functions required (m-bind and m-result are a must, and m-plus and m-zero are optional).

Unlike haskell which can choose an implementation based on the return type of return and bind, you do have to spell it out. The macro with-monad will wrap a set of expressions up in the correct monad, and the domonad monad comprehension form is also able to accept an optional monad name (useful if you aren't inside a with-monad form, or if you need a different monad)

Post reply on HN