Sunday, August 16, 2015

If True or False I Know Not

"I idly heard; if true or false I know not."
-- Shakespeare, King John
Act IV, Scene II, Line 124

Welcome Back


This is the next in the series of post on Dr. Graham Hutton's excellent paper, "A tutorial on the universality and expressiveness of fold", this time around we'll look at Oring.  Dr. Hutton has given Oring the following definition:

or :: [Bool] → Bool
or = fold (∨) False

The idea is that we Fold an Or function with a seed value of False.  If one of the members of the collection is True we Or it with False giving us True, else if none of the members of the collection are True we will end up with the value of False.


In the simple example below we'll see that if we have a single value of True then the end result will be True.

At the start we have a Seed value of False with collection containing False, True, and False.


First time the Memorize has False and X has False.


Second time the Memorize has False and X has True.


Third time the Memorize has True and X has False giving use the finally value of True.



Let us now look at this in sweet, sweet code.

Clojure

(ns fold-or)
(defn fold-or
"or = fold (∨) False"
[& facts]
(reduce #(or %1 %2) false facts))
view raw Fold_Or.clj hosted with ❤ by GitHub
(ns fold-or.tests
(require
[clojure.test :refer [deftest testing are run-tests]]
[fold-or :as sut]))
(deftest fold-or-tests
(testing "Given all true it must return true"
(are [truths] (true? (apply sut/fold-or truths))
[true]
[true true]
(repeat 100 true)))
(testing "Given all false it must return false"
(are [falsehoods] (false? (apply sut/fold-or falsehoods))
[false]
[false false]
(repeat 100 false)))
(testing "Given some true and false it must return true"
(are [facts] (true? (apply sut/fold-or facts))
[false true]
[true false]
[false true false]
[true false false])))
(run-tests)


In the Clojure code that we use the or macro and a seed value of false in order to create an Oring function using the higher order function of reduce.  Since reduce is expecting a function and not a macro we need to create a lambda function to wrap the or macro.

C#

using System.Linq;
namespace Folder
{
public static class Folder
{
public static bool Or(params bool[] facts)
{
return facts.Aggregate(false, (m, x) => m || x);
}
}
}
view raw Folder.cs hosted with ❤ by GitHub
using Xunit;
using static Folder.Folder;
namespace FolderTests
{
public class FolderTests
{
[Theory]
[InlineData(new[] { true })]
[InlineData(new[] { true, true })]
[InlineData(new[] { true, true, true })]
public void GivenOnlyTrueItMustReturnTrue(bool[] truths)
{
Assert.True(Or(truths));
}
[Theory]
[InlineData(new[] { false })]
[InlineData(new[] { false, false })]
[InlineData(new[] { false, false, false })]
public void GivenOnlyFalseItMustReturnFalse(bool[] falsehoods)
{
Assert.False(Or(falsehoods));
}
[Theory]
[InlineData(new[] { true, false })]
[InlineData(new[] { false, true })]
[InlineData(new[] { false, true, false })]
[InlineData(new[] { false, false, true })]
public void GivenSomeTrueAndFalseItMustReturnTrue(bool[] facts)
{
Assert.True(Or(facts));
}
}
}
view raw FolderTests.cs hosted with ❤ by GitHub


We see in the C# code that we can use the LINQ aggregate method on the collection we are folding.  We give the aggregate a seed value of false and in the lambda we simply takes the memorize and the current member and or them.

JavaScript (ECMAScript 2015)

let _ = require("lodash");
exports.foldOr = (...facts) =>
_.foldl(facts, (m, x) => m || x, false);
view raw foldOr.js hosted with ❤ by GitHub
let sut = require("../src/foldOr"),
expect = require("expect.js");
describe("foldOr", () => {
it("Given all true it must return true", () => {
expect(sut.foldOr(true)).to.be.ok();
expect(sut.foldOr(true, true)).to.be.ok();
expect(sut.foldOr(true, true, true)).to.be.ok();
}),
it("Given all false it must return false", () => {
expect(sut.foldOr(false)).not.to.be.ok();
expect(sut.foldOr(false, false)).not.to.be.ok();
expect(sut.foldOr(false, false, false)).not.to.be.ok();
}),
it("Given some true and false it must return true", () => {
expect(sut.foldOr(true, false)).to.be.ok();
expect(sut.foldOr(false, true)).to.be.ok();
expect(sut.foldOr(false, true, false)).to.be.ok();
expect(sut.foldOr(false, false, true)).to.be.ok();
});
});
view raw foldOrSpec.js hosted with ❤ by GitHub


Using lodash's foldl function along with Babel.js we are able to create an Oring function by folding over the collection and passing it to a lambda function which ors the current member of the collection with the memorize value.  We give a seed value of false thus causing the initial value of the memorize to be false.

Until Next Time


There you have it an Oring function using nothing but Fold.  Thus "proving" that all you need is Fold.