Re: _import in a functor

Phil Clayton <[email protected]> Wed, 03 Feb 2016 13:32:02 +0000
Newsgroups gmane.comp.lang.ml.mlton.user
Message-ID <[email protected]>
On 02/02/2016 17:42, Matthew Fluet wrote:
> On Tue, Feb 2, 2016 at 8:49 AM, Phil Clayton <[email protected]> wrote:
>> (I thought I had already asked about this issue but I can't find or remember
>> any answer.  Sorry if it's a duplicate.)
>>
>> It appears that _import can't be used inside a functor when the types of the
>> imported function depend on the functor's arguments.  See attached example.
>> Building with
>>
>>    mlton -default-ann 'allowFFI true' import_in_functor.sml
>>
>> gives
>>
>> Error: import_in_functor.sml 3.13.
>>    Invalid type for _import.
>>      int32 * t -> unit
>> compilation aborted: elaborate reported errors
>>
>> Is that intentional behaviour and something I should work around?
>
> It is intentional, in as much as we want to ensure that any functor
> that type checks at its declaration site will necessarily type check
> at every application site (that is, when we re-type-check the functor
> body with the actual argument at its use site).
>
> In your example, if you had
>
>    structure S2 = F (type t = int -> int)
>
> then that would not work, since "int -> int" is not a valid FFI type
> and the re-type-checking would result in the "Invalid type for
> _import" error message.

That seems a reasonable decision.  I think this could be usefully 
mentioned in
http://mlton.org/ForeignFunctionInterfaceSyntax
Perhaps at the end of the first section, something like:
"Inside a functor, before the functor's arguments are known, the type 
must elaborate to a correct form."


> Also, there are few cases where the same C function would work with
> multiple different SML types, so I wouldn't expect that there are very
> many situations where you could exploit an ability to include an
> _import in a functor.  The one exception is when the C function is
> taking a void* argument, for which multiple SML types have that same
> runtime C representation.  See,
> https://github.com/MLton/mlton/issues/53 for a similar proposal.  In
> that scenario, you might use something like:
>
> functor F (type t  val toPtr : t -> MLton.Pointer.t) = struct val f =
> _import "c_fun" : int * MLton.Pointer.t -> unit; end
>
> Now the application site need not know the details of or provide the
> right _import; instead, it simply witnesses how to convert to the
> generic FFI type.

I agree that there are limited opportunities to use _import in this way. 
  In my case it was different SML types for pointers, as you mention above.

By the way, in
https://github.com/MLton/mlton/issues/53
doesn't the proposal to have toPtr for vectors and arrays suffer from 
the problem that a garbage collection could relocate v between toPtr v 
and the foreign call?  (I think this came up in discussion about ways to 
pass a null char pointer, to support the C representation of an optional 
string.)


> Another potential problem with _import-s in functors is that they
> would be expanded to multiple _import-s overall, one for each functor
> application.  Each of those _import-s, with the same C function name,
> would result in a distinct C prototype (in the C codegen; no
> prototypes needed in the native codegens), which is often an error for
> the C compiler.

I found that I needed to move the _import out of the functor for another 
reason.  (I sometimes _import a diagnostic version of the C function 
that is specific to the type, although the non-diagnostic version is 
always the same.)  When I first encountered this a few years ago, I seem 
to recall that I found that I also had to move the _import outside the 
functor, which is probably why I didn't mention it then.  So I haven't 
actually found the current behaviour to be limiting.

Phil


------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140