Brett Rants


Functional Functions that Function

Mathematics ↠ Programming ↠ Philosophy

Functions: A Working Definition

Function: F(Input)↠Output

A Function is a Logical Operator that takes a Value, Transforms Said Value, and Returns a Value.

Or the same thing stated more verbosely:

A Function is a Logical Operator that takes a Value (meaning, Some Noun, which could be a Number, Letter, Character String, Person, Place, Soul, or any other construct), Transforms Said Value (so, we are talking about a Verb, here, making Addition, Subtraction, Living, Dying, and Moving Back Two Spaces all valid actions), and Returns a Value (another Noun, not necessarily the same as The First Noun).

Nothing (i.e. 0) is a Noun, as is The Empty Set (∅) or The Null Value (NULL).

Doing Nothing is a Verb, as is Pass, Ignore, or similar.

As an aside, I will note that a Function can ignore any given input and the end result is the same as if it was passed nothing.
def ignore_input(input):
    return 5
Thus, even if a Function Returns a Value, that does not necessitate (or even imply) that anything is ever done with The Returned Value.

The Trivial Function

The Trivial Function: F(∅)↠∅

The Trivial Function takes Nothing as its input, Does Nothing with it, and Returns a Null Value.

It's not very interesting.

Deterministic Functions

Deterministic Function: F(x)=F(x) For All x.

Or stated in English, given the same Input, a Deterministic Function will yield the same Output.

Deterministic Functions are Reliable, Predictable, and Mappable.


Given Function(Input)↠Output.

If For All Valid Inputs (For All i in Input) and All Outputs (All o in Output), there exists a Set of Tuples of The Form {i1:o1, i2:o2, ...} such that F(ix)=ox, then such a Set of Tuples is Called a Mapping.

As stated, All Deterministic Functions are Mappable.

Well Formed Functions

Well Formed Function: Any Function which yields equivalent results if replaced with its Mapping.

In short, Well Formed Functions are Atomic and do not have Side-Effects.

A Well Formed Function does not alter or effect anything outside of itself.

Well Formed Functions do not change Global Values.


Monad: A Well Formed Function that Does Nothing and Returns its Input as its Output.

Thus, a Monad is a Pass Through Function. A True Monad (or Pure Monad) is indistinguishable from The Identity Function.

Monads are ONLY interesting (i.e. useful) when that Do Nothing Part is stretched to its limits to the point where Nothing is Not Really Being Done; and rather, the something being done is Not Functionally Important or Mathematically Relevant to the task at hand.

Example Monad (that is nothing like a True Monad, but is a lot like The So-Called and/or Fake Monads used in Functional Programming): "Hold that thought," as I get myself a Cup of Hot Chocolate. "Now, where were we?"

Do not worry if you don't understand.

I promise not to mention Monads ever again... at least, not on this page.

Procedural Programming

Programming is little more than Stringing Functions Together. And the two simplest ways of Stringing Functions Together are either Sequentially or In Parallel.

For Well Formed Functions, both cases look pretty much the same.
def example_program():
    return "Success!"
If Run Sequentially, step_one Returns prior to step_two ever firing. Whereas, if Run In Parallel (also know as Asynchronous Execution) no such limitation exists and step_three may exit prior to step_one even beginning.

However, if either step_one, step_two, or step_three is Not Well Formed, The Execution Order can make a big difference.

Most Programs Run Sequentially. And most Programming Languages, assume Sequential Execution.

Certainly, if the above was Run in Python, step_one would exit prior to the start of step_two. But the addition of a few key-word async's here-and-there would change all that.

But as that's not really what this page is about, I'm going to skip all that and quietly move-on to a much more interesting way of Stringing Functions Together.

Composition: A First Try

F() G() H()

Wherein, The Output of F is used as The Input to G, whose Output in turn is used as The Input to H.

So it's easier to keep track of things down the line, let's make that a bit more verbose.

step_one() step_two() step_three()

And that is very similar to Command Line Pipes.

C:\>step_one | step_two | step_three

Which in turn (I believe), is very similar to Point Free Notation (namely, F.G.H or step_one.step_two.step_three). But don't quote me on that, as I could never get my Point Free Styled Commands to work with any degree of reliability back when I was experimenting with Haskell.

Rather, I often prefer a LISP style Notation, which uses endless Parentheses.


This may seem more complex at first, on account of the reverse ordering. But as the Parentheses Collapse in the exact same way that I learned back in Second Grade (or whenever that was), I am much more used to manipulating these sorts of constructions.

If the previous example_program is restructured, using a more LISP-like syntax with a few more parentheses (but the same key-words) the result is as follows:
I know those few changes don't provide much clarity. So, let me highlight two points:
Was that useful?

Probably not.

You know what, I'm just going to kill the key-words (all of them) and reduce the program to a set of parentheses.
( (
) )
And since White Space (Returns and Blank Spaces) are ignored in LISP, the foregoing can be reduced to a straightforward string of parentheses.


And if not to you, than at least to me, that last packs a lot of information. We are talking about an Outer Function that is dependent upon an Inner Function, which in turn is comprised of Four Discrete Steps.

Of course, some of you might be saying, "Duh! I knew that the second I saw The Python Code."

So, maybe, I should just say that if only Well Formed Functions are used, any number of Inner Functions (and thus, Inner Parentheses) may be removed and replaced by a key-word, in this case example_program

example_program = () = (((),(),(),()))

Where & When The Parentheses are placed is just matter of Where & When Additional Detail is Desired.

Composition: Just The Facts

If Function F has Input(F) of Type A and Output(F) of Type B and Function G has Input(G) of Type B and Output(G) of Type C, then there ALWAYS exists a Function H which has Input(H) of Type A and Output(H) of Type C such that G(F(A))=H(A). And the process of combining F & G is called Composition.

If F(A)↠B and G(B)↠C, then there exists a Composition H(A)↠C, such that H(A)=G(F(A)).

Math got you down?

Are Endless Parentheses slowly sapping your Will to Live? Or at least, causing Serious Annoyance and Eye Strain?

Then rejoice, for all that really matters is The Inter-Connect-Ability of Functions.

As long as The Types Match, New Functions can be built-up from Smaller Functions and Existing Functions can be broken-down into Smaller Functions ad infinitum.

In short, F(x) is Arbitrarily Divisible and Expandable.


Maybe, I should talk about Types for a second... but just a second.

A Type is another way of saying A Class of Objects.

A Type is The Name given to a Grouping of Nouns.

Type(Chicago) = Class City
Type(Banana) = Class Fruit
Type(Human) = Class Sentient

Of course, I could go down that list and give each Object (herein, Chicago, Banana, Human) a different Class, as Class is just an arbitrary way of Slicing & Dicing Reality.

Type(Chicago) = Class Crime Center
Type(Banana) = Class Snack Food
Type(Human) = Class Primate

Types & Classes are very much subjectively decided and could well be the subject of a whole other Rant, you know, if I cared about the subject that much.

What's relevant at the moment is that for two Functions to be Composible, The Output Type Class for The First Function must match The Input Type Class for The Second Function.

And having clarified that point, I will move on, never to mention it again.

Functional Programming

Functional Programming: A Programming Style which Exclusively Uses Only Well Formed Functions.

Sample Program Expansion


Since I am not working with a Real World Problem, The Expansion is Arbitrary.

In the above, if A & B have Side-Effects (are Not Well Formed Functions), then there may be unintended Cross Over between step_one and step_two and the firing order can matter immensely.

However, if A & B are Well Formed, there's insulation between the steps, the wires never cross, and the parentheses do their job. This makes reasoning about The Program much (much-much) easier, as A only effects A and step_one only effects step_one.

If there are no Side-Effects, Effects are limited to The Local Scope.
I really don't care about the latter. But the first two essentially mean The Act of Programming is Easier.

Game! Set! Match!

On Reasoning

This is a program.


This is the same program.
For me, there's information to be discovered in The Placement of The Parentheses.

It's like a game of Connect The Dots, trying to see Patterns & Groupings.

I believe I became a Better Programmer once I started to Deconstruct Problems in this way.

Of course, most problems can be handled quite well by a Linear Script.


So, there's no need to look for complexity, where it need not be.


Being who I am, just about as soon as I started to Program, I started Applying Programming Concepts to Philosophy.

Obviously, I don't have The Answers. But I do have a new way of Asking My Questions?

And I find the activity amusing and the use of Functions to be... um, Enlightening

next Brett Rants entry

Home Brett Rants Index

If Math Models Reality,
What Can That Model Tell Us About Reality?

I use the concept of Functions freely throughout this site. So, I just thought I would give a brief outline of what I mean when I use the term Function.

© copyright 2021 Brett Paufler