Informal fallacy causes stack overflow

c#, language-agnostic, logic

Solution

It is not very clear from your question what are you trying to do. Are you trying to express some logical predicates in C#? Are you trying to write code that will reason about logic? Are you trying to represent logical formulas?

Paradoxes. When talking about paradoxes in computations, it might be good to read about lambda calculus and Russel's paradox (here is a nice article). Lambda calculus is essentially a simple functional programming language (imagine C# with lambda functions and application, but nothing else).

It was first developed as a system for the foundation of mathematics (before computers were invented), but this did not really work because you were able to write recursive computations that did not make sense (see the article for details), but you can write a computation that evaluates as follows (in C# notation):

r(r) = not(r(r)) = not(not(r(r)))

... and since there is no `x = r(r)` such that `x = not(x)`, the model does not make sense as foundation of mathematics. But it is useful as a model of programming languages where you can write recursive computations - though they may never terminate.

Representing logic. If you want to represent logical formulas in your program, then you probably want to separate the representation of formula from the reasoning. This is best done in functional languages (like F#), but you can do it in C# too (just with more typing). The F# representation of a formula would be something like:

type Formula = 
  | Variable of string
  | Negation of Formula 
  | Implies of Formula * Formula

The idea is that a formula is either a variable (named) or a negation of another formula or an implication where one formula implies another. In C#, you can represent the same thing as a class hierarchy (with `Formula` as a base class and three derived classes.)

Your reasoning can then be implemented as a method that manipulates formulas. In F#, this can be done quite easily using pattern matching. In C#, you'll probably need to use type tests to write code that checks if the argument is `Variable` (then do something...); if the argument is `Negation` (then do something...) etc.

Problem

Broken code ``` public static partial class LogicExtensions { public static bool Implies<T>(this T premise, T conclusion) { return conclusion.Infers(premise); } public static bool Infers<T>(this T premise, T conclusion) { return premise.Implies(conclusion); } } ``` The code above is expecting to express: The conclusion infers the premise because of the premise implies the conclusion. The the premise implies the conclusion because of the conclusion infers the premise. It would be circular reasoning, and definitely will cause stack overflow. I then redesign it as follows: Working code ``` public delegate bool Paradox<T>(T premise, T conclusion, Paradox<T> predicate=null); public static partial class LogicExtensions { public static bool Implies<T>(this T premise, T conclusion, Paradox<T> predicate=null) { if(null==predicate) return conclusion.Infers(premise, Implies); if(Infers!=predicate) return predicate(premise, conclusion); return LogicExtensions.Implies(conclusion as IConvertible, premise as IConvertible); } public static bool Infers<T>(this T premise, T conclusion, Paradox<T> predicate=null) { if(null==predicate) return premise.Implies(conclusion, Infers); if(Implies!=predicate) return predicate(premise, conclusion); return LogicExtensions.Implies(conclusion as IConvertible, premise as IConvertible); } static bool Implies<T>(T premise, T conclusion) where T: IConvertible { var x=premise.ToUInt64(null); return x==(x&conclusion.ToUInt64(null)); } } ``` But that means: It fails on the correct logic that it cannot go without `Paradox<T>` which I initially named `Predicate<T>` but is conflict with `System.Predicate<T>`. It's defective that `T` must implement `IConvertable` unlike the code former. To be clear, I'm trying to make the code not only works but also represent like logical formulas that I can further reuse it to reason about logic without a constraint of `T` implements `IConvertable`. Is there a way make the logic correct and get rid of the defective design?

Original source

Related problems