4 ms·
The first example, naively translated to scheme, results in: (define (skip-many a) (or (and (a) (skip-many a)) (void))) This is not infini
by chandler 18y ago
The first example, naively translated to scheme, results in:
(define (skip-many a)
(or (and (a) (skip-many a))
(void)))
This is not infinite recursion. The Parser monad used in the Haskell version is simply a stream dressed in monadic clothes (and even C has streams a-la FILE*).
As for the second example, the naive translation to scheme is:
(define (print-n-times n s)
(cond
((zero? n) (void))
(else (put-str-ln s)
(print-n-times (sub1 n) s))))
Here, both Haskell & scheme demonstrate constant memory usage; not because of Monads, or strict/lazy evaluation, but because of tail recursion.
Also, in your first sentence, I think you meant "strict".
- shrughes 18y agoNeither of your translations convert your code to anything that has to do with monads, and your first translation is just plain broken. Your print-n-times doesn't return an action---it's an imperative function that performs an action. The naive translations to Scheme would be as follows: (define (skip-many p) (<|> (>> p (skip-many p)) (return 'nothing))) (define (print-n-times n s) (if (= 0 n) (return 'nothing) (>> (put-str-ln s) (print-n-times (- n 1) s)))) In order to fix the infinite recursion in my first example, the parsing framework I made in Scheme had a macro `thunk-parser` (actually, it had a shorter, stupid-sounding name) which for all intents and purposes just wraps the expression in a (lambda ()). (define (skip-many p) (<|> (>> p (thunk-parser (skip-many p))) (return 'nothing))) Also, both your examples rely heavily on non-strict evaluation. 'and' and 'or' are both macros that non-strictly evaluate expressions.
- chandler 18y agoAgreed; neither of the translations use monads, because monads are a semantic hand-job proscribing order within a declarative language. However, Scheme is not a declarative language, therefore order is implied in the structure, therefore monads aren't necessary. >> Your print-n-times doesn't return an action... Nope, look again. It returns the results of applying `void'. Who knows what (void) may return in a loosely-typed language? >> ...it's an imperative function that performs an action. Well, considering Scheme is an imperative language with side-effects, it's hard to dodge such criticism. >> The naive translations to Scheme would be as follows... That's not a translation from Haskell to Scheme, that's writing Haskell using a prefix syntax. >> Also, both your examples rely heavily on non-strict evaluation. 'and' and 'or' are both macros that non-strictly evaluate expressions. I went back and re-read your original post: >> ...you'll note that the translation, strictly evaluated, gives infinite recursion. Mea culpa--I completely missed your point that translating from a turing complete language to a non-turing complete language might have some pitfalls.
- shrughes 18y agoThen maybe I'm misunderstanding the point of your reply. I was pointing out how monads are inconvenient to use in strictly evaluated languages. Why did you follow up with an example about how not using monads is convenient?
- chandler 18y ago>> Then maybe I'm misunderstanding the point of your reply. I was pointing out that your examples don't make sense, as it's trivial to translate the Haskell code into another general purpose language (such as Scheme, C, Perl, Fortran, etc), while impossible to translate into an eager (strictly evaluated) language (such as...?). Additionally, the reason monads are cumbersome in other languages has nothing to do with eager/lazy evaluation, or conditional computation, and everything to do with the fact that monads exist in Haskell to solve it's sequencing problem (arising from the fact that it's a declarative language). Imperative languages have no problem with sequencing, and therefore have no need for monads.