archives

Sectioning a chain of operators and dot as reverse application

I have a meager syntax proposal and am curious if anyone has explored this design, knows of a language that uses it, or can think of a problem with it. It's comprised of two aspects that work together to support certain idioms in a neighborhood of Haskell syntax.

The first aspect is to generalize sectioning of binary operators to chains of binary operators where the first and/or last operand in the chain is missing. Here's a GHCi interaction:

Prelude> (1 + 2*)

    The operator `*' [infixl 7] of a section
        must have lower precedence than that of the operand,
          namely `+' [infixl 6]
        in the section: `1 + 2 *'

So Haskell doesn't like the expression (1 + 2*). The proposal is that this would instead be a section of an operator chain, equivalent to (λx. 1 + 2*x). Similarly for (*2 + 1).

The second aspect is to use dot for reverse application (rather than composition). That is,

x.f = f x

Dot and juxtaposition would have equal precedence allowing an OOP-like style (after modifying map and filter to take the list first):

[1, 2, 3].map (+1).filter (>2)  ===  filter (map [1, 2, 3] (+1)) (>2) 

In combination with the first aspect, we can recover composition as:

f `compose` g = (.g.f)

And in general we can capture the tails of OOP-like expressions like this:

frob = (.map (+1).filter (>2))

Has anyone used or seen this approach or does anyone see problems with it?

Policy as Types

Sophia Drossopolou, Greg Meredith, and I have written a paper demonstrating that we can use Caires' behavioral-spatial types to write security policies for objects in an ocap-secure language; then it's possible for the compiler to statically check that the implementation satisfies the policy. In an object capability language, dependency injection is the only way you get access to any ability to side-effect the world; all authority is embodied in object references, which are unforgeable. To deny someone the ability to perform an action, you simply do not give them a reference to the object that performs it. We focused on demonstrating that we can type deniability in the paper.

Lucius G Meredith, Mike Stay, Sophia Drossopoulou, "Policy as Types".

Greg and I are currently seeking crowdfunding to build a platform called splicious; should we get funded, part of our plan is to port the spatial logic model checker to Scala and add spatial-behavioral types as annotations with a plugin.

Currying in non-curried languages

There are a lot of currying-in-X tutorials floating around, for example I've written my own for Javascript and PHP.

Recently this one appeared on Hacker News and I got involved in the discussion, which made me think a bit harder about a peculiarity of my implementations which I've not seen in anyone else's.

My blog post on PHP discusses this peculiarity in the "Returning Functions" section. My Javascript implementation linked above was written before this discovery, but I've detailed it in this followup.

The idea with all implementations is that we make a 'curry' function such that the following hold:


// Curry a function
var curried = curry(function(a, b, c) { return [a, b, c]; });

// By the definition of currying
curried(x)(y)(z) == [x, y, z]

// For convenience and interoperability
curried(x, y, z) == curried(x)(y, z)
                 == curried(x, y)(z)
                 == curried(x)(y)(z)
                 == [x, y, z]

The difference in my implementations is what happens when we're given more arguments than the function's arity:


// Curry another function
var two_level = function(a, b, c) {
                  return function(d, e, f) {
                    return [a, b, c, d, e, f];
                  };
                };
var curried2 = curry(two_level);

// Most implementations pass all arguments once arity has been reached
curried2(u, v, w, x, y, z) == two_level(u, v, w, x, y, z)
                           == function(d, e, f) {
                                return [u, v, w, d, e, f];
                              };

// My implementations only pass the minimum number; the rest go to the return value
curried2(u, v, w, x, y, z) == two_level(u, v, w)(x, y, z)
                           == [u, v, w, x, y, z]

Two consequences of this are:

  • All function arities become constant (though overridable via wrappers)
  • Currying a manually-curried function (ie. a function which returns a function) will *uncurry* it, allowing both levels to be called as one!

My current implementations either pass all remaining arguments to the first return value (PHP) or pass one argument at a time to successive return values (Javascript; essentially "foldl ($) f args"). These work best when the returned functions are also curried, but there's no reason we can't curry them on-the-fly, or look up how many to supply and loop until we run out. We could even use such a loop to execute tail-calls while we're at it ;)

This uncurrying is effectively the same as the convenience functionality shown in the first code block, but extended to our return values as well as our arguments. In other words:

When we have too few values, we produce wrapper functions to accept the leftovers as their arguments.
When we have too many values, we consume wrapper functions by passing the leftovers as their arguments.

I'd love to hear people's opinions on this. Is my approach better, worse or complementary to the standard approach? Has this duality been noticed before? Is this just a reason not to use n-ary functions? ;)

Edit: In case you can't tell, my aim is to have expressions like "a(b, c, d, e, f, g, ...)" behave like a Haskell expression "a b c d e f g ...".