Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using F# Result discriminated union results in TypeLoadException

Tags:

f#

I've refactored some of my code to use (relatively newly introduced) F# Result type that is defined in FSharp.Core like this:

type Result<'TOk,'TError> = 
| Ok of 'TOk 
| Error of 'TError

Everything compiles but at runtime the application fails with the following exception:

Could not load type 'Microsoft.FSharp.Core.FSharpResult`2' from assembly 'SomeAssembly, Version=1.25.24.0, Culture=neutral, PublicKeyToken=null' due to value type mismatch.

If I copy the definition to my project so it shadows the original one, everything works.

The app.config has the following section:

  <dependentAssembly>
    <Paket>True</Paket>
    <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535" newVersion="4.4.1.0" />
  </dependentAssembly>

And the projects files are updated with the directive <TargetFSharpCoreVersion>4.4.1.0</TargetFSharpCoreVersion>

So I am not really sure what can cause this error. What is also strange is that the error message claims that FSharpResult is supposed to reside in project assembly, rather than FSharp.Core.dll.

UPDATE. As suggested in the comments, the problem only occurs when the application is built using Visual Studio 2015. Here's a small console program that reproduces the problem:

open System

[<EntryPoint>]
let main argv = 
    let result = Result.Ok "Hello"
    printfn "%A" result
    0

Open Visual Studio 2015, build and run the project, you should see this error: Unhandled Exception: System.TypeLoadException: Could not load type 'Microsoft.FSharp.Core.FSharpResult`2' from assembly 'ResultTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' due to value type mismatch. at Program.main(String[] argv)

If you have Visual Studio 2017 and rebuild the app with it, the app will work fine and prints the result: Ok "Hello"

like image 361
Vagif Abilov Avatar asked Jul 19 '17 12:07

Vagif Abilov


2 Answers

This is caused by F# 4.0 compiler using together with FSharp.Core 4.4.1.0, as described here:

https://github.com/Microsoft/visualfsharp/issues/3354

Workaround: Add FSharp.Compiler.Tools NuGet package to the affected projects as long as Visual Studio 2015 is used. Visual Studio 2017 works fine.

like image 194
Vagif Abilov Avatar answered Oct 19 '22 11:10

Vagif Abilov


In my case, using VS2015 IDE was a must, so we implemented our own version of the Result type:

type Result<'t, 'e> = | Ok of 't | Error of 'e

or you can even fine tune the type with your own error handling requirements, e.g.:

type Result<'t> =
        | Success of 't
        | Failure of (string * exn option) 

or

type Result<'t> =
        | Success of 't
        | Failure of (ErrorCode * string)
and ErrorCode = | Code1 | Code2 | Code3

I know it's not ideal, it's better if you have this types available in the F# core, but it did the trick :)

like image 37
jdearana Avatar answered Oct 19 '22 11:10

jdearana