Search code examples
f#mathnet-numerics

Error when using MathNet.Numerics Fit.Line with F# tuple type


I am working on a library in F# that calculates rheological parameters for a fluid using MathNet.Numerics. However, I'm encountering an issue when implementing the BinghamModel and GetBinghamModelFit functions.

Here's the code I'm using:

open MathNet.Numerics
open MathNet.Numerics.Optimization
open MathNet.Numerics.LinearAlgebra

let BinghamModel (tau0: float) (mu: float) (shearRate: float) =
    tau0 + mu * shearRate

let GetBinghamModelFit (shearRate: float[]) (shearStress: float[]) =
    let results = Fit.Line(shearRate, shearStress)
    let Tau0, Mu = results
    let shearStressCalculated = Array.map (BinghamModel Tau0 Mu) shearRate
    let RSquared = GoodnessOfFit.RSquared(shearStressCalculated, shearStress)
    (Tau0, Mu, RSquared)

However, I'm encountering the following error during compilation: "One tuple type is a struct tuple, the other is a reference tuple"

It seems that the Fit.Line function returns a struct tuple (float * float) whereas I'm using reference tuples (float, float) in my code.

How can I resolve this issue and make my code work with the Fit.Line function provided by MathNet.Numerics? I have followed the example provided by the library creators, but it's not working as expected.

remark: I added the MathNet.Numerics and MathNet.Numerics.FSharp nugets to my project. Any insights or suggestions would be greatly appreciated!

I attempted different approaches to resolve the issue with the Fit.Line function in MathNet.Numerics returning a struct tuple (float * float) while I was using reference tuples (float, float) in my code.

Attempt 1:

let Tau0, Mu = ref(results)

Expected: I expected that using ref would allow me to capture the values from the struct tuple and store them in reference tuples. Outcome: Unfortunately, this approach did not work as expected, and I still encountered the error.

Attempt 2:

let Tau0, Mu = struct(results)

Expected: I hoped that using struct would somehow convert the struct tuple to reference tuples. Outcome: This approach also did not work as intended, and I still faced the same error.

Attempt 3:

let Tau0, Mu = box results :?> float * float

Expected: I thought that explicitly casting results to the expected tuple type might resolve the issue. Outcome: While the compiler did not raise any complaints, when I used the function in an F# script, it resulted in an error. In summary, despite trying these different approaches, I haven't been able to successfully convert the struct tuple (float * float) returned by Fit.Line into the reference tuple (float, float) that my code requires.

I appreciate any guidance or insights on how to properly handle this type conversion issue and make my code work seamlessly with the Fit.Line function.


Solution

  • You should be able to use the struct keyword in the pattern part of let to deconstruct a struct tuple:

    let struct(Tau, Mu) = Fit.Line(shearRate, shearStress)