Happy New Year, and welcome to the first newsletter of 2022!
When we started work on Wikifunctions, we divided the work into eleven functional phases, named after the first eleven letters of the Greek alphabet (a naming scheme that has received notoriety recently). We are currently working on Phase η (eta), with the goal of entirely re-doing the function model of Wikifunctions by allowing for generic types and functions.
Following discussions within the team, we are refining the completion criteria for the current phase, in order to make it more tangible. The original idea of how to show that we had completed the phase was that we would do a lot of very deep static validation, so that a function call such as:
(1) if(head([true]), false, true)
would validate, but
(2) if(head(["text"]), false, true)
would not. To explain: the if
function requires a Boolean
as the first argument, but head
is currently defined as head(List) → Object
. So in a static analysis, if
requires a Boolean
but gets an Object
. But if we would say that this is OK, the static analysis for both (1) and (2) would pass - and (2) shouldn’t pass.
On the other hand, as well as static analysis we have dynamic analysis, which happens when running the code. In that one, (1) should pass and return false
, whereas (2) should raise a type error during evaluation (something such as “if
expects a Boolean
on the first argument, but got a String
”).
We decided to de-scope the deep static analysis for now. This is something that we can add later, possibly after launching Wikifunctions.org. As you can see, users would get error messages one way or the other: it is just a question of when exactly the error is raised. Also, if you are interested in working on these or similar topics, please reach out. We are always happy to integrate the work of volunteers and other external partners.
Instead of this static analysis, we decided to focus on the following capabilities as examples of how the phase will have been completed:
curry
as a composition on the wiki, but without requiring strict static analysispositive integer
, sign
, and integer
Let’s dive deeper into each of these capabilities.
For this to work, a user must be able to use a function as an argument, and use that function for a function call in the implementation of curry
. What is curry? Curry is a standard function in computer science that takes a function f and another object x and runs the function on the object. The standard form is that the function f has two arguments, the first one being of the type of x, and the 'output' is a call to the function f with the second argument preset to the value x. Example: given a function that appends a string to another string, I could create a new function “add s to end
” by calling curry(append, "s")
. We want to make it possible to define and call such a function.
The following things will need to be possible:
Positive Integer
, with a single key value
of type String
Positive Integer
value
contains a character which is not a digit (0-9), the validator raises a user-created error with the non-digit charactervalue
contains leading zeros and is not just a single zero, the validator raises a user-created errorvalue
is an empty string, the validator raises a user-created errorPositive Integer
typeIs zero: Positive Integer → Boolean
(returns True
if the argument is zero and False
otherwise)Successor: Positive Integer → Positive Integer
(returns the argument increased by one)BigInt
) and Python (bignum
)Predecessor: Positive Integer → Positive Integer
(returns the argument decreased by one, raises an error in case the argument is zero)BigInt
) and Python (bignum
)Positive Integer: String → Positive Integer
(constructor)Positive Integer as String: Positive Integer → String
(deconstructor)Equal Positive Integer: Positive Integer, Positive Integer → Boolean
(whether the two numbers have the same value)Greater Than: Positive Integer, Positive Integer → Boolean
(whether the first number is bigger than the second)Lesser Than: Positive Integer, Positive Integer → Boolean
(whether the second number is bigger than the first)The following things will be possible, related to the mathematics term "sign":
Sign
, with a single key identity
of type Sign
Sign
, i.e. positive
, negative
, and neutral
Sign
Sign
typeEqual sign: Sign, Sign → Boolean
(returns True if the two arguments have the same value)The following things will be possible:
Integer
, with two keys, absolute value
of type Positive Integer
and sign
of type Sign
Integer
sign
is neutral
and absolute value
is not zero
, or vice versa, raise an errorInteger
typeInteger: Positive Integer, Sign → Integer
(constructor)Absolute value: Integer → Positive Integer
(deconstructor)Sign: Integer → Sign
(deconstructor)Equal Integer: Integer, Integer → Boolean
(whether the two numbers have the same value)Greater Than: Integer, Integer → Boolean
(whether the first number is bigger than the second)Lesser Than: Integer, Integer → Boolean
(whether the second number is bigger than the first)A generic wrapper is a function that takes a type and returns a newly constructed type that has a single key with a value of that type. Wrappers may be useful for example to make sure that we don’t accidentally treat something as a number that looks a lot like a number. It is also useful as a test case because it is a rather simple generic type.
Wrap Type: Type → Type
Wrap: Type T → Function
which is a function that returns a function of signature T → Wrap Type(T)
Unwrap: Type T → Function
which is a function that returns a function of signature Wrap Type(T) → T
Wrap Type(Boolean)
as an object on the wikiWrap Type(T)
, e.g. Wrapped Equality: Type T → λ: Wrap(T), Wrap(T) → Boolean
Unwrap(Boolean)(Wrap(Boolean)(True))
and get True
backThere are still quite a few tasks to be done in this phase, but many of the pieces are almost in place for it. Once this phase is complete, we will focus on getting the beta cluster ready for you to play with.
We wish you all the best for the New Year!