Fsharp: internal error: Generic Struct DU failing in fsi and dotnet fsi

Created on 2 Nov 2019  路  3Comments  路  Source: dotnet/fsharp

Getting this error, while playing with http://www.fssnip.net/7Wn/title/Phantom-type-example in fsi

error FS0193: internal error: Could not load type 'CustomerID' from assembly 'FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

Repro steps

  • run dotnet fsi or fsi
  • run the following code
[<Struct>]
type ID<'T> = ID of System.Guid

type CustomerID = interface end
type ProductID = interface end

// Now you can create ID<CustomerID> and 
// ID<ProductID> values to represent two kinds of IDs:

let newCustomerID () : ID<CustomerID> = ID(System.Guid.NewGuid())
let newProductID () : ID<ProductID> = ID(System.Guid.NewGuid())

// The nice thing about this is that you can write functions that work with any ID easily:

let printID (ID g) = printfn "%s" (g.ToString())

// For example, I can now create one customer ID, one product ID and print 
// both, but I cannot do equality test on those IDs, because they're types do not match:

let ci = newCustomerID ()
let pi = newProductID ()
printID ci
printID pi

Expected behavior

evaluates and prints.

Actual behavior

error FS0193: internal error: Could not load type 'CustomerID' from assembly 'FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

Known workarounds

add ;; to force evaluation between the types, as @zpodlovics explains below.

Related information

Microsoft (R) F# Interactive version 10.6.0.0 for F# 4.7

Area-FSI Resolution-Duplicate Severity-Low bug

Most helpful comment

The following code will work (please note the ";;" at the end of type definitions) if you copy & paste into dotnet fsi console:

[<Struct>]
type ID<'T> = ID of System.Guid;;
type CustomerID = interface end;;
type ProductID = interface end;;

// Now you can create ID<CustomerID> and 
// ID<ProductID> values to represent two kinds of IDs:

let newCustomerID () : ID<CustomerID> = ID(System.Guid.NewGuid())
let newProductID () : ID<ProductID> = ID(System.Guid.NewGuid())

// The nice thing about this is that you can write functions that work with any ID easily:

let printID (ID g) = printfn "%s" (g.ToString())

// For example, I can now create one customer ID, one product ID and print 
// both, but I cannot do equality test on those IDs, because they're types do not match:

let ci = newCustomerID ()
let pi = newProductID ()
printID ci
printID pi

Tested on Ubuntu 18.04 Linux x86_64 with 3.0.100 .NET Core SDK.
Microsoft (R) F# Interactive version 10.6.0.0 for F# 4.7

All 3 comments

The following code will work (please note the ";;" at the end of type definitions) if you copy & paste into dotnet fsi console:

[<Struct>]
type ID<'T> = ID of System.Guid;;
type CustomerID = interface end;;
type ProductID = interface end;;

// Now you can create ID<CustomerID> and 
// ID<ProductID> values to represent two kinds of IDs:

let newCustomerID () : ID<CustomerID> = ID(System.Guid.NewGuid())
let newProductID () : ID<ProductID> = ID(System.Guid.NewGuid())

// The nice thing about this is that you can write functions that work with any ID easily:

let printID (ID g) = printfn "%s" (g.ToString())

// For example, I can now create one customer ID, one product ID and print 
// both, but I cannot do equality test on those IDs, because they're types do not match:

let ci = newCustomerID ()
let pi = newProductID ()
printID ci
printID pi

Tested on Ubuntu 18.04 Linux x86_64 with 3.0.100 .NET Core SDK.
Microsoft (R) F# Interactive version 10.6.0.0 for F# 4.7

I believe this may be a very long-standing reflection-emit limitation

Let's use https://github.com/dotnet/fsharp/issues/10060 as the canonical issue for this

Was this page helpful?
0 / 5 - 0 ratings