3 ms·
There's one thing that should be mentioned here: you can easily compose these things. You can do: echo = forever $ getLine >>= putStrLn This also works wi
by exDM69 12y ago
There's one thing that should be mentioned here: you can easily compose these things. You can do:
echo = forever $ getLine >>= putStrLn
This also works with do notation, if you'd want to make the greet example looping.
greetLoop = forever $ do
name <- getLine
putStrLn ("Hello, " ++ name)
This is a very powerful concept. In mainstream imperative programming languages, you can't assign "statements" to variables or return them from functions or pass them as parameters.
- jeorgun 12y agoMaybe I'm misinterpreting you, but isn't that effectively what a closure is in an imperative language? def forever loop do yield end end forever do name = gets puts "Hello, name" end or even template <typename F> void forever(const F& fn) { for (;;) fn(); } int main() { forever([] { std::string str; getline(std::cin, str); std::cout << "Hello, " << str << '\n'; }); } looks a lot like the above code to me.
- exDM69 12y agoWell, in this simple example it is trivial to do the same by wrapping statements in a closure, but it's a bit more nuanced than that. But you still can't assign a for-loop as a value to a variable, for example (to exaggerate a little). This becomes more apparent when using monads for non-IO applications like parsing. It's difficult (but not impossible, of course) to implement things like backtracking or non-determinism by writing lots of closures in an imperative programming language, they don't compose as nicely. There are parser combinator libraries (similar to Parsec) done in other languages of course, but some of them even implement monads in the language they work in. I recall seeing "class Monad" written in Python, I think it was in the pyparsec library.