Soldalma
Soldalma

Reputation: 4758

Why adding some packages breaks my code?

I noticed that adding packages sometimes breaks my code. Functions like Seq.replicate and List.take that were working get red squiggly lines and the program no longer runs. Here is a detailed procedure that should replicate the problem (I am using VS Community Edition 2017):

1) Create a project.

2) Program.fs contains the code:

[<EntryPoint>]
let main argv =
    printfn "%A" argv
    0 // return an integer exit code

3) Add two lines of code as follows:

[<EntryPoint>]
let main argv =
    let repla = Seq.replicate 10 "A"
    printfn "%A" (repla |> List.ofSeq |> List.take 5)
    printfn "%A" argv
    0 // return an integer exit code

3) Hit Ctrl+F5, the program runs without any problems.

4) Right-click on References on the Solution Explorer. Click on Manage Nuget Packages....

5) Click on Browse.

6) Search for Newtonsoft.Json and install it.

7) Hit Ctrl+F5, the program runs without any problems. The console prints

["A"; "A"; "A"; "A"; "A"]
[||]

8) Proceed as in steps 4 to 6 and install package MathNet.Numerics using Nuget.

9) Hit Ctrl+F5, the program runs without any problems. The console prints

["A"; "A"; "A"; "A"; "A"] [||]

10) Proceed as in steps 4 to 6 and install package MathNet.Numerics.FSharp using Nuget.

11) Click on the Program.fs tab. The dreaded red squiggly lines appeared under Seq.replicateandList.take`.

12) Hit Ctrl+F5. A dialog box pops up with the following message:

There were build errors. Would you like to continue and run the last successful build?

Questions:

a) What exactly is happening?

b) Is this an isolated case related to a problem in MathNet.Numerics.FSharp or the specific combination of packages installed, or the order in which they were installed? Or is this a common problem?

c) Is it possible to avoid this problem while using Nuget?

d) If not, is it possible to avoid this problem by installing by some other means (not Nuget)?

Upvotes: 3

Views: 213

Answers (2)

s952163
s952163

Reputation: 6324

Well, I think the OP's concerns are somewhat valid. I would discourage hand-editing the fsproj file. And also the comments are very valid too, Paket is a great tool that can simplify dependency management both in VS and Code. So here's a very simple, two part answer, where a) you can actually get your solution working using nugget and without hand-editing the project file, and b) get a quick intro to how using paket on VS.

This issue where some package downloads and old dependency that messes up other code occurs now and then and is probably due to a strategy of relying on the minimum viable version. Your issue is somewhat similar to this Q: Why can't I get suave to work.

Here's the simplest solution using just nugget:

  1. Open a new solution with an fsharp console project
  2. At this point your Fsharp.Core in VS2017 will be 4.1:

enter image description here

  1. Now add Mathnet.Numerics.Fsharp via nugget:

enter image description here

Now, very unfortunately you got downgraded to F# 3.1

  1. This is no good, so just get Fsharp.Core via nugget as well!

enter image description here

  1. And voila, you're back to a working solution without needing to edit fsproj. Basically all you had to do is add the Fsharp.Core package. You could have also changed the .NET Framework option in properties and move it to .NET 4.7 with Fsharp 4.1:

enter image description here

Now for Part 2 of the answer with Paket (btw, the Paket plugin just got updated and I tested and it works fine). You can essentially use it as a replacement for nugget or directly edit the files. You actually need to work with two files, paket.dependencies in the solution root and paket.references in the project root. Paket.lock will be generated. Here's a two-step process to get started. Take the project you just made above and from the Tools menu in VS select Paket Dependencies Manager, do Initialize Paket, then do Convert From Nuget:

enter image description here

With this you can keep managing your dependencies with nuget or use paket if you like. Next I will add Newtonsoft.JSON to the references. Double-click on the paket.dependencies file and add the following line: nuget Newtonsoft.Json 10.0.3 restriction: >= net452 , you only actually need Newtonsoft.Json in there but we don't want to download the whole interweb called .NetCore. Also add this line to paket.references (you can just click on it in the project explorer): Newtonsoft.Json. And the run Tools | Paket | Install:

Paket.dependencies:

enter image description here

Paket.references:

enter image description here

And Run Paket Install:

enter image description here

And you will have Newtonsoft.JSON installed. Usually you don't need to specify a version of framework restriction, however it has some pre-release package that you might not want, and also I assume you don't need the .netcore dependencies.

You can actually right click and try install this package from the references Add Package menu, but you will bump into dependency errors.

enter image description here

enter image description here

Upvotes: 3

MathNet.Numerics.FSharp has a dependency to FSharp.Core.3.1.2.5 which replaces the current version of FSharp.Core you are using. Being quite old 3.1.2.5 lacks many functions.

This happens with other popular F# libraries such as FsCheck as well. I usually change the reference to the newest version of FSharp.Coreas that should be backward compatible.

To do so I unload the F# project and update the FSharp.Core reference in the project file to:

<Reference Include="FSharp.Core">
  <Name>FSharp.Core</Name>
  <AssemblyName>FSharp.Core.dll</AssemblyName>
  <HintPath>$(MSBuildProgramFiles32)\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\$(TargetFSharpCoreVersion)\FSharp.Core.dll</HintPath>
</Reference>

Then I reload the project.

As this is a rather clunky procedure hopefully more insightful users will post a better solution.

Upvotes: 6

Related Questions