The point is to parse the input into a structure which always upholds the predicates you care about so you don't end up continuously defensively programming in ifs and asserts.
The point is to parse the input into a structure which always upholds the predicates you care about so you don't end up continuously defensively programming in ifs and asserts.
def TRUE(a, b):
return a
def FALSE(a, b):
return b
def IF(cond, a, b):
return cond(a, b)
assert IF(TRUE, 1, 2) == 1
assert IF(FALSE, 1, 2) == 2
This gives you the conditional statement in most languages ("cond ? a : b" or "a if cond else b").I had to work with this for a while because I wanted to implement Hello World in Javascript. https://github.com/quchen/lambda-ski/blob/master/helloworld/...
## type Silly = Foo | Bar Int | Qux String Silly
## Constructors
def Foo(onFoo, onBar, onQux):
return onFoo()
def Bar(arg0):
return lambda onFoo, onBar, onQux: onBar(arg0)
def Qux(arg0, arg1):
return lambda onFoo, onBar, onQux: onQux(arg0, arg1)
## Values of Silly type are Foo, Bar(x) and Qux(x, y)
## Destructor
def match_Silly(silly, onFoo, onBar, onQux):
return silly(onFoo, onBar, onQux)
You can make a whole language on top of that if you don't mind effectively disabling your CPU's branch predictor.I'd summarise boolean blindness as: implicit (often unsafe) coupling/dependencies of method results; which could instead be explicit data dependencies. That article's example is 'plus x y = if x=Z then y else S(plus (pred x) y)', which uses an unsafe 'pred' call that crashes when x is 'Z'. It avoids the crash by branching on an 'x=Z' comparison. The alternative is to pattern-match on x, to get 'Z' or 'S x2'; hence avoiding the need for 'pred'.
Another alternative is to have 'pred' return 'Maybe Nat'; although that's less useful when we have more constructors and more data (e.g. the 'NonEmptyList' in this "parse, don't validate" article!)
const published = posts.filter(post => !post.draft);