Algorithms that don't terminate in a lazy language - functional-programming

According to http://www.reddit.com/r/programming/comments/gwqa2/the_real_point_of_laziness/c1rslxk
Some algorithms don't terminate in an eager language, that do in a lazy one, and (a mild shocker for me to find,) vice-versa.
The former is of course well known, but the latter strikes me as, if true, considerably more than a mild shocker.
Does anyone know an algorithm that terminates in an eager language but not in a lazy one?

Wikipedia answers this question for lambda calculus: Lambda Calculus Reduction Strategies
The key parts are:
Applicative order is not a normalising strategy. [...] In contrast, normal order is so called because it always finds a normalising reduction if one exists.
This shows an even stronger property of lazy evaluation: if there is an evaluation strategy that makes a particular program terminate, then the program also terminates with lazy evaluation. So in particular strict evaluation (applicative order) does not allow any program to terminate that loops under lazy evaluation.
The references on the wikipedia page provide proofs.

I'm going to go out on a limb and state that no algorithm that terminates in a pure functional eager environment, will fail to terminate in a pure functional lazy environment.
The article that was being discussed does not mention this, the comment is followed by a request for an example that is not meet. Therefore until an example is found I'm going to say no.

Related

which is more general recursion or iteration?

is Recursion is more general than Iteration?
for me Iteration means repetitive control using language constructs other than subroutine calls (like loop-constructs and/or explicit
goto’s), whereas recursion means as repetitive control obtained using subroutine calls). which is more general in these two?
Voted to close as likely to prompt opinion-based responses; my opinion-based response is: recursion is more general because:
it's simply a user-case of function calls, which a language will already have; and
recursion captures both a direct one-to-one pattern of repetition and more complicated patterns, such as tree traversal, divide and conquer, etc.
Conversely iteration tends to be a specific language-level construct allowing only a direct linear traversal.
In so far as it is not opinion-based, the most reasonable answer is that neither recursion nor iteration is more general than the other. A language can be Turing complete with recursion but no iteration (minimal Lisps are like that) and a language can also be Turing complete with iteration but no recursion (earlier versions of Fortran didn't support recursion). Both recursion and iteration are widely used. Iteration is probably more commonly used since for every person who learns programming with something like Lisp or Haskell there are probably a dozen who learn programming with things like Java or Visual Basic -- but I don't think that "most commonly used" is a good synonym for "general".

Functional programming, in what areas is it inefficient and why is it hard to determine space and time cost?

I have been reading up on functional programming and I have two questions that I was hoping someone could help me with.
I've read that lazy functional programs can be inefficient if you are accessing the same data often because of the extra overhead of checking whether the expression has been evaluated. I have also read in the first answer of the following thread (Are functional programming languages suitable for graphics programming?), that functional programming can be resource demanding in the context of graphical programming because it creates a lot of temporary objects (I assume this has to do with having to create new objects to simulate state?).
Are there any other areas where functional programming might end up being resource heavy / inefficient in compairison to OOP/procedural programming?
I have read in the first answer in the following thread (Pitfalls/Disadvantages of Functional Programming), that "it is very difficult to predict the time and space costs of evaluating a lazy functional program". Could someone give a simple (if that exists) explaination of why this is the case? I assume it has to do with lazy evaluation only evaluation expressions when needed, but why is it not simple to predict kind of a worst case scenario that is similar to imperative programming where everything is evaluated?
I've read that lazy functional programs can be inefficient if you are accessing the same data often because of the extra overhead of checking whether the expression has been evaluated.
This involves checking a tag bit on a pointer. It is cheap.
functional programming can be resource demanding in the context of graphical programming because it creates a lot of temporary objects
This depends on the implementation. Allocation in pure FP languages is cheap, as immutability means you can avoid some write barriers. Object allocation is roughly similar to OO languages, though some GCs, such as GHCs, are very efficient compared to e.g. Java.
Are there any other areas where functional programming might end up being resource heavy / inefficient in compairison to OOP/procedural programming?
There are plenty of problems that require very tight resource usage. E.g. operating systems. In such environments you need libraries for direct access to hardware and the ability to mutate memory in place. Depending on the functional language implementation you're using, you may or may not have this.
it is very difficult to predict the time and space costs of evaluating a lazy functional program
It is harder to model lazy evaluation costs because the amount of work done, and when it is done, depends on the input data, which is only available at runtime.
Practically, languages let you choose whether you want to use strict or lazy evaluation, as neither are appropriate for all situations.

Is recursion a feature in and of itself?

...or is it just a practice?
I'm asking this because of an argument with my professor: I lost credit for calling a function recursively on the basis that we did not cover recursion in class, and my argument is that we learned it implicitly by learning return and methods.
I'm asking here because I suspect someone has a definitive answer.
For example, what is the difference between the following two methods:
public static void a() {
return a();
}
public static void b() {
return a();
}
Other than "a continues forever" (in the actual program it is used correctly to prompt a user again when provided with invalid input), is there any fundamental difference between a and b? To an un-optimized compiler, how are they handled differently?
Ultimately it comes down to whether by learning to return a() from b that we therefor also learned to return a() from a. Did we?
To answer your specific question: No, from the standpoint of learning a language, recursion isn't a feature. If your professor really docked you marks for using a "feature" he hadn't taught yet, that was wrong.
Reading between the lines, one possibility is that by using recursion, you avoided ever using a feature that was supposed to be a learning outcome for his course. For example, maybe you didn't use iteration at all, or maybe you only used for loops instead of using both for and while. It's common that an assignment aims to test your ability to do certain things, and if you avoid doing them, your professor simply can't grant you the marks set aside for that feature. However, if that really was the cause of your lost marks, the professor should take this as a learning experience of his or her own- if demonstrating certain learning outcomes is one of the criteria for an assignment, that should be clearly explained to the students.
Having said that, I agree with most of the other comments and answers that iteration is a better choice than recursion here. There are a couple of reasons, and while other people have touched on them to some extent, I'm not sure they've fully explained the thought behind them.
Stack Overflows
The more obvious one is that you risk getting a stack overflow error. Realistically, the method you wrote is very unlikely to actually lead to one, since a user would have to give incorrect input many many times to actually trigger a stack overflow.
However, one thing to keep in mind is that not just the method itself, but other methods higher or lower in the call chain will be on the stack. Because of this, casually gobbling up available stack space is a pretty impolite thing for any method to do. Nobody wants to have to constantly worry about free stack space whenever they write code because of the risk that other code might have needlessly used a lot of it up.
This is part of a more general principle in software design called abstraction. Essentially, when you call DoThing(), all you should need to care about is that Thing is done. You shouldn't have to worry about the implementation details of how it's done. But greedy use of the stack breaks this principle, because every bit of code has to worry about how much stack it can safely assume it has left to it by code elsewhere in the call chain.
Readability
The other reason is readability. The ideal that code should aspire to is to be a human-readable document, where each line describes simply what it's doing. Take these two approaches:
private int getInput() {
int input;
do {
input = promptForInput();
} while (!inputIsValid(input))
return input;
}
versus
private int getInput() {
int input = promptForInput();
if(inputIsValid(input)) {
return input;
}
return getInput();
}
Yes, these both work, and yes they're both pretty easy to understand. But how might the two approaches be described in English? I think it'd be something like:
I will prompt for input until the input is valid, and then return it
versus
I will prompt for input, then if the input is valid I will return it, otherwise I get the input and return the result of that instead
Perhaps you can think of slightly less clunky wording for the latter, but I think you'll always find that the first one is going to be a more accurate description, conceptually, of what you are actually trying to do. This isn't to say recursion is always less readable. For situations where it shines, like tree traversal, you could do the same kind of side by side analysis between recursion and another approach and you'd almost certainly find recursion gives code which is more clearly self-describing, line by line.
In isolation, both of these are small points. It's very unlikely this would ever really lead to a stack overflow, and the gain in readability is minor. But any program is going to be a collection of many of these small decisions, so even if in isolation they don't matter much, it's important to learn the principles behind getting them right.
To answer the literal question, rather than the meta-question: recursion is a feature, in the sense that not all compilers and/or languages necessarily permit it. In practice, it is expected of all (ordinary) modern compilers - and certainly all Java compilers! - but it is not universally true.
As a contrived example of why recursion might not be supported, consider a compiler that stores the return address for a function in a static location; this might be the case, for example, for a compiler for a microprocessor that does not have a stack.
For such a compiler, when you call a function like this
a();
it is implemented as
move the address of label 1 to variable return_from_a
jump to label function_a
label 1
and the definition of a(),
function a()
{
var1 = 5;
return;
}
is implemented as
label function_a
move 5 to variable var1
jump to the address stored in variable return_from_a
Hopefully the problem when you try to call a() recursively in such a compiler is obvious; the compiler no longer knows how to return from the outer call, because the return address has been overwritten.
For the compiler I actually used (late 70s or early 80s, I think) with no support for recursion the problem was slightly more subtle than that: the return address would be stored on the stack, just like in modern compilers, but local variables weren't. (Theoretically this should mean that recursion was possible for functions with no non-static local variables, but I don't remember whether the compiler explicitly supported that or not. It may have needed implicit local variables for some reason.)
Looking forwards, I can imagine specialized scenarios - heavily parallel systems, perhaps - where not having to provide a stack for every thread could be advantageous, and where therefore recursion is only permitted if the compiler can refactor it into a loop. (Of course the primitive compilers I discuss above were not capable of complicated tasks like refactoring code.)
The teacher wants to know whether you have studied or not. Apparently you didn't solve the problem the way he taught you (the good way; iteration), and thus, considers that you didn't. I'm all for creative solutions but in this case I have to agree with your teacher for a different reason: If the user provides invalid input too many times (i.e. by keeping enter pressed), you'll have a stack overflow exception and your solution will crash. In addition, the iterative solution is more efficient and easier to maintain. I think that's the reason your teacher should have given you.
Deducting points because "we didn't cover recursion in class" is awful. If you learnt how to call function A which calls function B which calls function C which returns back to B which returns back to A which returns back to the caller, and the teacher didn't tell you explicitly that these must be different functions (which would be the case in old FORTRAN versions, for example), there is no reason that A, B and C cannot all be the same function.
On the other hand, we'd have to see the actual code to decide whether in your particular case using recursion is really the right thing to do. There are not many details, but it does sound wrong.
There are many point of views to look at regarding the specific question you asked but what I can say is that from the standpoint of learning a language, recursion isn't a feature on its own. If your professor really docked you marks for using a "feature" he hadn't taught yet, that was wrong but like I said, there are other point of views to consider here which actually make the professor being right when deducting points.
From what I can deduce from your question, using a recursive function to ask for input in case of input failure is not a good practice since every recursive functions' call gets pushed on to the stack. Since this recursion is driven by user input it is possible to have an infinite recursive function and thus resulting in a StackOverflow.
There is no difference between these 2 examples you mentioned in your question in the sense of what they do (but do differ in other ways)- In both cases, a return address and all method info is being loaded to the stack. In a recursion case, the return address is simply the line right after the method calling (of course its not exactly what you see in the code itself, but rather in the code the compiler created). In Java, C, and Python, recursion is fairly expensive compared to iteration (in general) because it requires the allocation of a new stack frame. Not to mention you can get a stack overflow exception if the input is not valid too many times.
I believe the professor deducted points since recursion is considered a subject of its own and its unlikely that someone with no programming experience would think of recursion. (Of course it doesn't mean they won't, but it's unlikely).
IMHO, I think the professor is right by deducting you the points. You could have easily taken the validation part to a different method and use it like this:
public bool foo()
{
validInput = GetInput();
while(!validInput)
{
MessageBox.Show("Wrong Input, please try again!");
validInput = GetInput();
}
return hasWon(x, y, piece);
}
If what you did can indeed be solved in that manner then what you did was a bad practice and should be avoided.
Maybe your professor hasn't taught it yet, but it sounds like you're ready to learn the advantages and disadvantages of recursion.
The main advantage of recursion is that recursive algorithms are often much easier and quicker to write.
The main disadvantage of recursion is that recursive algorithms can cause stack overflows, since each level of recursion requires an additional stack frame to be added to the stack.
For production code, where scaling can result in many more levels of recursion in production than in the programmer's unit tests, the disadvantage usually outweighs the advantage, and recursive code is often avoided when practical.
Regarding the specific question, is recursion a feature, I'm inclined to say yes, but after re-interpreting the question. There are common design choices of languages and compilers that make recursion possible, and Turing-complete languages do exist that don't allow recursion at all. In other words, recursion is an ability that is enabled by certain choices in language/compiler design.
Supporting first-class functions makes recursion possible under very minimal assumptions; see writing loops in Unlambda for an example, or this obtuse Python expression containing no self-references, loops or assignments:
>>> map((lambda x: lambda f: x(lambda g: f(lambda v: g(g)(v))))(
... lambda c: c(c))(lambda R: lambda n: 1 if n < 2 else n * R(n - 1)),
... xrange(10))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
Languages/compilers that use late binding, or that define forward declarations, make recursion possible. For example, while Python allows the below code, that's a design choice (late binding), not a requirement for a Turing-complete system. Mutually recursive functions often depend on support for forward declarations.
factorial = lambda n: 1 if n < 2 else n * factorial(n-1)
Statically typed languages that allow recursively defined types contribute to enabling recursion. See this implementation of the Y Combinator in Go. Without recursively-defined types, it would still be possible to use recursion in Go, but I believe the Y combinator specifically would be impossible.
From what I can deduce from your question, using a recursive function to ask for input in case of input failure is not a good practice. Why?
Because every recursive functions call gets pushed on to the stack. Since this recursion is driven by user input it is possible to have an infinite recursive function and thus resulting in a StackOverflow :-p
Having a non recursive loop to do this is the way to go.
Recursion is a programming concept, a feature (like iteration), and a practice. As you can see from the link, there's a large domain of research dedicated to the subject. Perhaps we don't need to go that deep in the topic to understand these points.
Recursion as a feature
In plain terms, Java supports it implicitly, because it allows a method (which is basically a special function) to have "knowledge" of itself and of others methods composing the class it belongs to. Consider a language where this is not the case: you would be able to write the body of that method a, but you wouldn't be able to include a call to a within it. The only solution would be to use iteration to obtain the same result. In such a language, you would have to make a distinction between functions aware of their own existence (by using a specific syntax token), and those who don't! Actually, a whole group of languages do make that distinction (see the Lisp and ML families for instance). Interestingly, Perl does even allow anonymous functions (so called lambdas) to call themselves recursively (again, with a dedicated syntax).
no recursion?
For languages which don't even support the possibility of recursion, there is often another solution, in the form of the Fixed-point combinator, but it still requires the language to support functions as so called first class objects (i.e. objects which may be manipulated within the language itself).
Recursion as a practice
Having that feature available in a language doesn't necessary mean that it is idiomatic. In Java 8, lambda expressions have been included, so it might become easier to adopt a functional approach to programming. However, there are practical considerations:
the syntax is still not very recursion friendly
compilers may not be able to detect that practice and optimize it
The bottom line
Luckily (or more accurately, for ease of use), Java does let methods be aware of themselves by default, and thus support recursion, so this isn't really a practical problem, but it still remain a theoretical one, and I suppose that your teacher wanted to address it specifically. Besides, in the light of the recent evolution of the language, it might turn into something important in the future.

2 questions at the end of a functional programming course

Here seems to be the two biggest things I can take from the How to Design Programs (simplified Racket) course I just finished, straight from the lecture notes of the course:
1) Tail call optimization, and the lack thereof in non-functional languages:
Sadly, most other languages do not support TAIL CALL
OPTIMIZATION. Put another way, they do build up a stack
even for tail calls.
Tail call optimization was invented in the mid 70s, long
after the main elements of most languages were developed.
Because they do not have tail call optimization, these
languages provide a fixed set of LOOPING CONSTRUCTS that
make it possible to traverse arbitrary sized data.
a) What are the equivalents to this type of optimization in procedural languages that don't feature it?
b) Do using those equivalents mean we avoid building up a stack in similar situations in languages that don't have it?
2) Mutation and multicore processors
This mechanism is fundamental in almost any other language you
program in. We have delayed introducing it until now for
several reasons:
despite being fundamental, it is surprisingly complex
overuse of it leads to programs that are not amenable
to parallelization (running on multiple processors).
Since multi-core computers are now common, the ability
to use mutation only when needed is becoming more and
more important
overuse of mutation can also make it difficult to
understand programs, and difficult to test them well
But mutable variables are important, and learning this mechanism
will give you more preparation to work with Java, Python and many
other languages. Even in such languages, you want to use a style
called "mostly functional programming".
I learned some Java, Python and C++ before taking this course, so came to take mutation for granted. Now that has been all thrown in the air by the above statement. My questions are:
a) where could I find more detailed information regarding what is suggested in the 2nd bullet, and what to do about it, and
b) what kind of patterns would emerge from a "mostly functional programming" style, as opposed to a more careless style I probably would have had had I continued on with those other languages instead of taking this course?
As Leppie points out, looping constructs manage to recover the space savings of proper tail calling, for the particular kinds of loops that they support. The only problem with looping constructs is that the ones you have are never enough, unless you just hurl the ball into the user's court and force them to model the stack explicitly.
To take an example, suppose you're traversing a binary tree using a loop. It works... but you need to explicitly keep track of the "ones to come back to." A recursive traversal in a tail-calling language allows you to have your cake and eat it too, by not wasting space when not required, and not forcing you to keep track of the stack yourself.
Your question on parallelism and concurrency is much more wide-open, and the best pointers are probably to areas of research, rather than existing solutions. I think that most would agree that there's a crisis going on in the computing world; how do we adapt our mutation-heavy programming skills to the new multi-core world?
Simply switching to a functional paradigm isn't a silver bullet here, either; we still don't know how to write high-level code and generate blazing fast non-mutating run-concurrently code. Lots of folks are working on this, though!
To expand on the "mutability makes parallelism hard" concept, when you have multiple cores going, you have to use synchronisation if you want to modify something from one core and have it be seen consistently by all the other cores.
Getting synchronisation right is hard. If you over-synchronise, you have deadlocks, slow (serial rather than parallel) performance, etc. If you under-synchronise, you have partially-observed changes (where another core sees only a portion of the changes you made from a different core), leaving your objects observed in an invalid "halfway changed" state.
It is for that reason that many functional programming languages encourage a message-queue concept instead of a shared state concept. In that case, the only shared state is the message queue, and managing synchronisation in a message queue is a solved problem.
a) What are the equivalents to this type of optimization in procedural languages that don't feature it? b) Do using those equivalents mean we avoid building up a stack in similar situations in languages that don't have it?
Well, the significance of a tail call is that it can evaluate another function without adding to the call stack, so anything that builds up the stack can't really be called an equivalent.
A tail call behaves essentially like a jump to the new code, using the language trappings of a function call and all the appropriate detail management. So in languages without this optimization, you'd use a jump within a single function. Loops, conditional blocks, or even arbitrary goto statements if nothing else works.
a) where could I find more detailed information regarding what is suggested in the 2nd bullet, and what to do about it
The second bullet sounds like an oversimplification. There are many ways to make parallelization more difficult than it needs to be, and overuse of mutation is just one.
However, note that parallelization (splitting a task into pieces that can be done simultaneously) is not entirely the same thing as concurrency (having multiple tasks executed simultaneously that may interact), though there's certainly overlap. Avoiding mutation is incredibly helpful in writing concurrent programs, since immutable data avoids a lot of race conditions and resource contention that would otherwise be possible.
b) what kind of patterns would emerge from a "mostly functional programming" style, as opposed to a more careless style I probably would have had had I continued on with those other languages instead of taking this course?
Have you looked at Haskell or Clojure? Both are heavily inclined to a very functional style emphasizing controlled mutation. Haskell is more rigorous about it but has a lot of tools for working with limited forms of mutability, while Clojure is a bit more informal and might be more familiar to you since it's another Lisp dialect.

What are the alternative of monads to use IO in pure functional programming?

monads are described as the haskell solution to deal with IO. I was wondering if there were other ways to deal with IO in pure functional language.
What alternatives are there to monads for I/O in a pure functional language?
I'm aware of two alternatives in the literature:
One is a so-called linear type system. The idea is that a value of linear type must be used exactly one time: you can't ignore it, and you can't use it twice. With this idea in mind, you give the state of the world an abstract type (e.g., World), and you make it linear. If I mark linear types with a star, then here are the types of some I/O operations:
getChar :: World* -> (Char, World*)
putChar :: Char -> World* -> World*
and so on. The compiler arranges to make sure you never copy the world, and then it can arrange to compile code that updates the world in place, which is safe because there is only one copy.
The uniqueness typing in the language Clean is based on linearity.
This system has a couple of advantages; in particular, it doesn't enforce the total ordering on events that monads do. It also tends to avoid the "IO sin bin" you see in Haskell where all effectful computations are tossed into the IO monad and they all get totally ordered whether you want total order or not.
The other system I'm aware of predates monads and Clean and is based on the idea that an interactive program is a function from a (possibly infinite) sequence of requests to a (possibly infinite) sequence of responses. This system, which was called "dialogs", was pure hell to program. Nobody misses it, and it had nothing in particular to recommend it. Its faults are enumerated nicely in the paper that introduced monadic I/O (Imperative Functional Programming) by Wadler and Peyton Jones. This paper also mentions an I/O system based on continuations which was introduced by the Yale Haskell group but which was short-lived.
Besides linear types, there's also effect system.
If by "pure" you mean "referentially transparent", that is, that an applied function is freely interchangeable with its evaluated result (and therefore that calling a function with the same arguments has the same result every time), any concept of stateful IO is pretty much excluded by definition.
There are two rough strategies that I'm aware of:
Let a function do IO, but make sure that it can never be called twice with the exact same arguments; this side-steps the issue by letting the functions be trivially "referentially transparent".
Treat the entire program as a single pure function taking "all input received" as an argument and returning "all output produced", with both represented by some form of lazy stream to allow interactivity.
There are a variety of ways to implement both approaches, as well as some degree of overlap--e.g., in the second case, functions operating on the I/O streams are unlikely to be called twice with the same part of the stream. Which way of looking at it makes more sense depends on what kind of support the language gives you.
In Haskell, IO is a type of monad that automatically threads sequential state through the code (similar to the functionally pure State monad), such that, conceptually, each call to an otherwise impure function gets a different value of the implicit "state of the outside world".
The other popular approach I'm aware of uses something like linear types to a similar end; insuring that impure functions never get the same arguments twice by having values that can't be copied or duplicated, so that old values of the "state of the outside world" can't be kept around and reused.
Uniqueness typing is used in Clean
Imperative Functional Programming by Peyton Jones and Wadler is a must read if you are interested in functional IO. The other approaches that they discuss are:
Dialogues which are lazy streams of responses and requests
type Dialogue = [Response] -> [Request]
main :: Dialogue
Continuations - each IO operation takes a continuation as argument
Linear types - the type system restricts you in a way that you cannot copy or destroy the outside state, which means that you can't call a function twice with the same state.
Functional Reactive Programming is another way to handle this.
I was wondering if there were other ways to deal with IO in a pure functional language.
Just adding to the other answers already here:
The title of this paper says it all :-)
You could also look at:
Rebelsky S.A. (1992) I/O trees and interactive lazy functional programming. In: Bruynooghe M., Wirsing M. (eds) Programming Language Implementation and Logic Programming. PLILP 1992. Lecture Notes in Computer Science, vol 631. Springer, Berlin, Heidelberg
When Haskell was young, Lennart Augustsson wrote of using system tokens as the mechanism for I/O:
L. Augustsson. Functional I/O Using System Tokens. PMG Memo 72, Dept Computer Science, Chalmers University of Technology, S-412 96 Göteborg, 1989.
I've yet to find a online copy but I have no pressing need for it, otherwise I suggest contacting the library at Chalmers.

Resources