Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defining functions that take no arguments or multiple at once #180

Open
Avaq opened this issue Dec 27, 2017 · 4 comments
Open

Defining functions that take no arguments or multiple at once #180

Avaq opened this issue Dec 27, 2017 · 4 comments

Comments

@Avaq
Copy link
Member

Avaq commented Dec 27, 2017

Consider this function:

f ('a', 'b') ('c') ()

Currently def cannot express its type. I would like to explore changes to its API to allow for the definition of any sort of JavaScript function (except methods).


More lists

-def :: String -> StrMap (Array TypeClass) -> NonEmpty (Array Type) -> AnyFunction -> AnyFunction
+def :: String -> StrMap (Array TypeClass) -> NonEmpty (Array (Array Type)) -> Type -> AnyFunction -> AnyFunction

The type could be encoded as a list of lists of Types specifying function input, and a single Type argument specifying output (we have to move it to a separate argument to keep the types consistent). So our f function could be defined as such:

def ('f')
    ({})
    ([[a, b], [c], []]) // input
    (d)                 // output
    (body)

We can encode "multiple arguments at once" and "no arguments" by using the second level of lists. I like this solution, because the input specification mirrors function application exactly:

('f') ({}) ([[a, b], [c], []])
  f          (a, b)  (c)  ()

If we would go for this solution, my preference would be to make a change to the $Function-api to use the same approach to specifying its type. But this is not required.


Taking a function definition as input

-def :: String -> StrMap (Array TypeClass) -> NonEmpty (Array Type) -> AnyFunction -> AnyFunction
+def :: String -> StrMap (Array TypeClass) -> Type -> AnyFunction -> AnyFunction

The Type there would have to be a Function type as defined by $Function. Since $Function is already capable of expressing complex function types by means of nesting, this would be sufficient to define f:

def ('f')
    ({})
    ($Function ([a, b, $Function([c, $Function([d])])]))
    (body)

Additional thoughts

We won't necessarily have to change the def API. We can implement def on top of, say, defn as a variant optimised for pure curried functions:

defn ("K") ({}) ([[a], [b]]) (a) //or:
defn ("K") ({}) ($Function ([a, $Function([b, a])]))

def  ("K") ({}) ([a, b, a])
@Avaq
Copy link
Member Author

Avaq commented Dec 27, 2017

We also briefly discussed (offline) the possibility of unifying the def API and the $Function API. I'm writing it down just to remember. The idea being that if we move the constraints argument to after the argument list, we could almost say that:

const $Function = def ('(anonymous)')

And $Function (args) would return a function still waiting for its type variable constraints and implementation, which could in turn be provided by the outer function at calltime.

@davidchambers
Copy link
Member

There are several exciting ideas here. I'm not yet sure what we should do, but it doesn't seem right for $.Function to be able to describe function types which def itself cannot. I ❤️ the idea of unifying these functions, but the fact that they relate differently to type variables may prevent this.

@davidchambers
Copy link
Member

Are you still interested in this functionality, @Avaq?

@Avaq
Copy link
Member Author

Avaq commented Jan 8, 2020

There's a lot of functionality, including this, I would like to have in order to achieve the broader goal of maturing sanctuary-def as a domain modelling tool. But because the scope of work to achieve this is so large, I tend to focus my attention elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants