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

external functions can't be specified with a type that is a function #7176

Closed
vicuna opened this issue Mar 11, 2016 · 7 comments
Closed

external functions can't be specified with a type that is a function #7176

vicuna opened this issue Mar 11, 2016 · 7 comments
Milestone

Comments

@vicuna
Copy link

vicuna commented Mar 11, 2016

Original bug ID: 7176
Reporter: goswin
Status: closed (set by @mshinwell on 2016-12-07T17:55:56Z)
Resolution: not a bug
Priority: normal
Severity: feature
Version: 4.02.3
Target version: 4.03.1+dev
Category: ~DO NOT USE (was: OCaml general)
Monitored by: @hcarty

Bug description

external expects a type that is a function. But it seems to require an actual "->" token instead of a type that represents a function.

Steps to reproduce

type t = c -> unit;;

type t = c -> unit

external stub : t = "stub";;

Error: External identifiers must be functions

@vicuna
Copy link
Author

vicuna commented Mar 11, 2016

Comment author: @alainfrisch

The number of syntactic "->" in external declaration defines the arity of the external function. This information is required to generate proper code to call the function.

@vicuna
Copy link
Author

vicuna commented Mar 13, 2016

Comment author: goswin

and why doesn't t carry that information?

@vicuna
Copy link
Author

vicuna commented Mar 14, 2016

Comment author: @alainfrisch

Indeed, one could probably allow the simple case where the type is entirely described by a named functional type:

 type t = int -> int
 external foo: t = "..."

But the fact that:

 type t = int -> int
 external foo: int -> t = "..."

is different from:

 type t = int -> int
 external foo: int -> int -> int = "..."

is a feature.

@vicuna
Copy link
Author

vicuna commented Mar 15, 2016

Comment author: junsli

I see, interesting. It is actually documented already:

http://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec414

@vicuna
Copy link
Author

vicuna commented Mar 15, 2016

Comment author: goswin

From the docs:
"Type abbreviations are not expanded when determining the arity of a primitive."

Maybe an exception should be made when only an abbreviated type is given. That should be a small change.

I would say in your example

external foo: int -> t = "..."
is
external foo: int -> (int -> int) = "..."

The extra () denoting a single return type. Just like int -> (int -> int) -> int has 2 arguments, one of them being a closure the foo returns a closure.

From the docs:

"For instance,

    type int_endo = int -> int
    external f : int_endo -> int_endo = "f"
    external g : (int -> int) -> (int -> int) = "f"

f has arity 1, but g has arity 2. This allows a primitive to return a functional value (as in the f example above): just remember to name the functional return type in a type abbreviation."

I think that's inconsistent. f and g should both have arity 1. The syntax with extra () around functional return types might actually make it clearer for ocaml function in general that they consume the first argument(s) and return a closure consuming any followup arguments. Execution wise there is a difference between

let f x y = Printf.printf "x = %d, y = %d, x+y = %d\n" x y (x+y); x+y
and
let g x = Printf.printf "x = %d, " x; function y -> Printf.printf "y = %d, x+y = %d\n" y (x+y); y

Why not show this in the type?

@vicuna
Copy link
Author

vicuna commented Mar 24, 2016

Comment author: @damiendoligez

@Goswin

external foo: int -> (int -> int) = "..."

The extra () denoting a single return type. Just like int -> (int -> int) -> int has 2 arguments, one of them being a closure the foo returns a closure.

That's really not a good idea. If we start using parentheses like this, how do you explain the associativity of "->" ? Currently you can just say that a->b->c is the same as a->(b->c).

Why not show this in the type?

What you want is function types with arity, maybe a good idea IMO, but it requires huge changes in the type system and in the language syntax. We certainly are not going to do it just to solve a minor problem in an obscure part of the system.

@Frisch

Indeed, one could probably allow the simple case where the type is entirely described by a named functional type:

type t = int -> int
external foo: t = "..."

Introducing a special case: rarely a good thing...

You have to do a cost/benefit analysis here.

@vicuna
Copy link
Author

vicuna commented Mar 25, 2016

Comment author: goswin

@doligez

What you want is function types with arity, maybe a good idea IMO, but it requires huge changes in the type system and in the language syntax. We certainly are not going to do it just to solve a minor problem in an obscure part of the system.

Yes. Which the () would show in a simple way.

But you have me convinced. The change in the type system would far too large and you would have to solve the problem of passing int->int->int to a function expecting int->(int->int) or vice versa and so on. The issue can be closed, it's as documented and I see why.

@vicuna vicuna closed this as completed Dec 7, 2016
@vicuna vicuna added this to the 4.03.1 milestone Mar 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant