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

Signature files are incompatible with an abstract exception record containing a function field #10520

Closed
2BitSalute opened this issue Nov 21, 2020 · 3 comments

Comments

@2BitSalute
Copy link

Repro steps

Consider this signature file, Test.fsi:

module Test
type exception_type
exception TestException of exception_type
val throw_test_exception: unit -> unit

With this implementation file, Test.fs:

module Test
type exception_type = { value: unit -> unit }
exception TestException of exception_type
let throw_test_exception (): unit =
    let r = { value = (fun () -> ()) }
    raise (TestException r)

Expected behavior

The program compiles

Actual behavior

Compiler error:

The type definitions for type 'exception_type' in the signature and implementation are not compatible because the signature requires that the type supports the interface System.Collections.IStructuralEquatable but the interface has not been implemented

Known workarounds

Originally asked on StackOverflow

  1. Not using a signature file

    suggested by one of the commenters, who also wondered whether the signature file feature is unofficially deprecated - true?

  2. Excluding the function-typed field from the exception record

    this is what I did in my actual code - I originally ended up with this compiler error because I lazily typed my exception with the module's main type, which happened to contain a function field

  3. Making the record type concrete, rather than abstract

    suggested by the answer to my SO question; this somewhat defeats the purpose of using a signature file

  4. ? - some way to "support the interface IStructuralEquatable"?

    My sense now is that this can't be done in "user land" - accurate?

Context: I'm coming to F# from OCaml, where signature files and abstract types are widely used, so I'm very hesitant to accept #1 or #3

Related information

  • Operating system: Windows 10
  • .NET Runtime kind: .NET Core
  • Editing Tools: Visual Studio Code
@cartermp
Copy link
Contributor

Firstly, welcome to F# and I hope you have a great time :)

Your best options are 2 and 3. An abstract type definition that is made concrete in the implementation like this just isn't supported in interface files. You need an explicit signature either via the type definition or inline on the exception type.

@2BitSalute
Copy link
Author

Could the compiler error be more clear, then? It makes it sound like the user can take some action to make the type comply with the requirement.

Also, could it be possible to support such a type in interface files in the future?

@cartermp
Copy link
Contributor

It likely won't ever be supported, since the F# design is just one where you have explicit signatures in signature files. Being able to swap out an implementation for an entirely abstract type just isn't a goal in the language.

I suppose the compiler error could be made more clear - we'd be happy to take a look at a PR that improves it, but we're unlikely to do it ourselves since the scenario is fairly niche.

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

2 participants