Importing FSharp.Charting in .fs file fails - f#

Create a new FSharp Console project via VS2015
Add FSharp.Data and FSharp.Charting nuget package.
In Program.fs import both the packages
open FSharp.Charting
open Fsharp.Data
After the import I am able to use functions provided in FSharp.Data package but not in FSharp.Charting.
NOTE: In case of script (.fsx) file, which created in the same project, I am able to use both after adding their reference.
I just wanted to to know if there are any steps i am missing for adding any reference in a .fs file. If yes then why does it work with respect to FSharp.Data package.

I think if you search SO you'll find a few examples of displaying charts with FSharp.Charting. It's not exactly clear what sort of error are you getting. Assuming you are on Windows this should work:
open FSharp.Charting
open System
[<STAThread>]
[<EntryPoint>]
let main argv =
Chart.Line [ for x in 0 .. 10 -> x, x*x ] |> Chart.Show
printfn "%A" argv
0 // return an integer exit code
You will need to add references to System.Windows.Forms, System.Windows.Forms.DataVisualization and System.Drawing.

Related

Meaning of CsvProvider error "The given key was not present in the dictionary" when trying to load sample file?

I am having trouble loading the csv files with FSharp.Data csv provider provided by fslab, including the sample adwords.csv file.
What does this error below mean? Also, when I hover over the code in the Visual studio editor it mentions that "The given key was not present in the dictionary"
Problem example:
#load "packages/FsLab/FsLab.fsx"
open System.IO
open FSharp.Data
"adwords.csv"
|> File.ReadAllLines
let test = CsvProvider<"adwords.csv">.GetSample()
The output:
>
val it : string [] =
[|"Criteria ID,Name,Canonical Name,Parent ID,Country Code,Target Type,Status";
"1000010,Abu Dhabi,"Abu Dhabi,Abu Dhabi,United Arab Emirates",9041082,AE,City,Active";
"1000011,Ajman,"Ajman,Ajman,United Arab Emirates",9047096,AE,City,Active";
"1000012,Al Ain,"Al Ain,Abu Dhabi,United Arab Emirates",9041082,AE,City,Active";
"1000013,Dubai,"Dubai,Dubai,United Arab Emirates",9041083,AE,City,Active";
"2004,Afghanistan,Afghanistan,,AF,Country,Active"|]
>
>System.MethodAccessException: Attempt by method '<StartupCode$FSI_0007>.$FSI_0007.main#()' to access method 'FSharp.Data.Runtime.CsvFile`1<System.__Canon>.Create(System.Func`3<System.Object,System.String[],System.__Canon>,
at <StartupCode$FSI_0007>.$FSI_0007.main#() in C:\test.fsx:line 11
Stopped due to error
I ran into this problem with my own files, so I grabbed this sample file from here: https://raw.githubusercontent.com/fsharp/FSharp.Data/master/tests/FSharp.Data.Tests/Data/Adwords.csv
Debug info:
If I delete the FSharp.Data library folder (v 2.3.0) and replace with version 2.2.5 it works correctly with no error.
If I don't use the FsLab.fsx script and instead use
#I "packages/FSharp.Data/lib/net40
#r "FSharp.Data.dll"
then everything works.
The path to the FsLab.fsx script is correct, it runs when I send the line to fsi.
The F# version is 14.0.23413.0.
The version of FSharp.Data downloaded by FSlab is FSharp.Data.2.3.0.
I have no other references in the .fsx script.
I am using Visual Studio Community edition 14.0.24720.00 Update 1.
.NET version 4.6.01038
I am realizing now that I am not getting the popup asking if I want to allow the .dll like I think I used to get when I used this before.
There is nothing wrong with the file. This for example works:
#load #"..\..\FSLAB\packages\FsLab\FsLab.fsx"
open System.IO
open FSharp.Data
[<Literal>]
let csvFile = #"C:\tmp\adwords.csv"
File.Exists csvFile
type Csv = CsvProvider<csvFile>
let csv = Csv.Load(csvFile)
csv.Rows
There is something wrong with your FsLab of FSharp.Data installation or type providers security maybe. Try the following, specify the path to the file directly. If it still doesn't work just nuget FSharp.Data and try using the csv type provider directly in a new project.
Other info is also helpful. VS version, FSLab version, wha other references you have. etc.
EDIT: Thanks for the debug info. That's actually quite helpful. VS2015 Update 1 broke two things, the Binding Redirect for Fsharp and the type providers (that might have been FSharp Tools, I forgot). I would upgrade to Update 2. If that's not possible please check if your FSharp.Data.TypeProviders.dll is in C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.3.0.0\Type Providers.
As referencing the dlls directly works, it's probably a version mismatch issue. My FsLab install predates VS2015 Update 1 and 2, so will see if it behaves differently with a new download.
There is some issue with the installation of FSharp.Data currently bundled with FsLab (as of June 2016). This issue is with version 2.3.0. If you instead use FSharp.Data 2.2.5 the code works as expected.
Delete the packages/FSharp.Data folder and replace with version 2.2.5. I did it from an old installation but you could do it from Nuget

#load a package in F# interactive (FSharpChart.fsx)

Hi i'm a noob and asking this newbie question, please forgive me.
I've installed successfully FSharpChart in my local directory
...
Added package 'MSDN.FSharpChart.dll.0.60.0' to folder 'C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Expert in F\packages'
Added package 'MSDN.FSharpChart.dll.0.60.0' to 'packages.config'
Successfully installed 'MSDN.FSharpChart.dll 0.60.0' to Expert in F
now, if i do
#load "FSharpChart.fsx";;
^^^^^^^^^^^^^^^^^^^^^^^
stdin(4,1): error FS0078: Unable to find the file 'FSharpChart.fsx' in any of
C:\Users\Fagui\AppData\Local\Temp
additional info:
inside this folder, i see a nupkg file, and a lib directory
Inside the lib directory, there is a dll, and a pdf file,
but i don't see any .fsx file.
basically, F# has installed the package in the active folder for the current project, and F#interactive is in another folder ?? bit strange ?
should i install another time the package ? or what is the way around it ?
thanks
UPDATE:
i don't know why, but apparently when i installed the FSharpChart package, I only got the dll, no fsx file
i managed to load it doing
#I #"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Expert in F"
#r #"packages\MSDN.FSharpChart.dll.0.60\lib\MSDN.FSharpChart.dll";;
unfortunately, typing the script in F# interactive
open MSDN.FSharp.Charting
let rnd = System.Random()
let rand() = rnd.NextDouble()
let randomPoints = [for i in 0 .. 1000 -> 10.0 * rand(), 10.0 * rand()]
randomPoints |> FSharpChart.Point;;
doesn't yield any chart, but just returns a list
val rnd : Random
val rand : unit -> float
val randomPoints : (float * float) list =
[(9.765916457, 2.272289941); (0.8211438594, 1.625466995);
...
(7.783786034, 7.572208311); (6.497914692, 3.66987128); ...]
val it : ChartTypes.PointChart
this may be due to the fact that the library is not supported anymore, and that i should use a newer library like Thomas Petricek indicated.
So, i did manage to install FSharp.Charting instead
let rnd = System.Random()
let rand() = rnd.NextDouble()
let randomPoints = [for i in 0 .. 1000 -> 10.0 * rand(), 10.0 * rand()]
randomPoints |> Chart.Point;;
and it did work
There is a newer version of the FSharpChart.fsx library which is called F# Charting, so first of all, I would recommend using this newer library instead (the API is quite similar, but F# Charting has a number of improvements).
The documentation for F# Charting also has a detailed page on referencing the library.
Typically, when you reference the library using NuGet, you'll need to specify relative reference:
// On Mac OSX use packages/FSharp.Charting.Gtk.0.90.13/FSharp.Charting.Gtk.fsx
#load "packages/FSharp.Charting.0.90.13/FSharp.Charting.fsx"
Where 0.90.13 is the version of the library that you got from NuGet (you may need to check the folder name - the path references in #load are relative to the place where your script lives).
Yes, F# Interactive is independent of the current project.
Use:
#load #"C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Expert in F\packages\FSharpChart.fsx";;
Also you can use the #I directive if you need to reference assemblies of a specific folder, see the reference.

How to implement a read table function in F#? (like Vlookup)

I need a function.
When I enter 0~15 and Protection, it'll return 45%.
Just like Vlookup function in Excel.
Is there a function like this one in F#?
(At website try F#, Learn -> Financial Modeling -> Using the Yahoo Finance Type Provider
It recommended us to use Samples.Csv.dll. However, I failed to install it and don't want to install that package just for a function :(.. )
I followed the tutorial (http://fsharp.github.io/FSharp.Data/library/CsvProvider.html)
and tried to run the program on my computer. But I am in trouble now
It couldn't identify the type CsvProvider (So I can't use the function Stocks.Load.)
What's the problem..?
This is how the code looks when using the CSV type provider in F# Data. To get this to work, you'll need to add reference to FSharp.Data.dll. The best way to do this is to install the package from NuGet. In Visual Studio, it will add reference for you, and in command line you can say:
nuget install FSharp.Data
Alternatively, if you are in an F# script file, then you need to install the nuget package and then add #r #"C:\path\to\FSharp.Data.dll". Then you can write the following:
open FSharp.Data
// Generate type based on a local copy with sample data
type Data = CsvProvider<"sample.csv">
// Load actual data from a file (this can be a different file with the same structure)
let loaded = Data.Load("runtime/file/name.csv")
// Find row for a specified age range & look at the properties
let row = loaded.Data |> Seq.find (fun r -> r.Age = "0~15")
row.Protection
row.Saving
row.Specified
A very simple way to do this is with a DataTable:
open System.Data
open System.IO
open LumenWorks.Framework.IO.Csv
let vlookup =
let table = new DataTable()
do
use streamReader = new StreamReader(#"C:\data.csv")
use csvReader = new CsvReader(streamReader, hasHeaders=true)
table.Load(csvReader)
table.PrimaryKey <- [|table.Columns.["Age"]|]
fun age (column: string) -> table.Rows.Find([|age|]).[column]
//Usage
vlookup "0~15" "Protection" |> printfn "%A"
There's no lack of CSV readers out there. I used this especially fast one (also available on NuGet).

Using NLog with F# Interactive in Visual Studio - Need documentation

I have a need to capture the input and output of F# functions when using F# Interactive. I am able to get NLog to work just fine when the program is run under Visual Studio using F5 or Ctrl-F5. Also the same methods that contain statements to output to the log work just fine and are called when invoked via F# Interactive; just nothing in the log file.
I also tried the following with F# Interactive to setup references to NLog and still nothing in the log when run from F# Interactive.
#I #"..\packages\NLog.2.0.0.2000\lib\net40"
#r #"NLog.dll"
And I even found this which led me to try each of these
NLog.Config.SimpleConfigurator.ConfigureForConsoleLogging()
NLog.Config.SimpleConfigurator.ConfigureForFileLogging(<full file name>)
and still nothing in the log file.
Anyone know if Nlog can be used with F# Interactive?
If so, how is it done?
EDIT
I was able to get NLog to work with fsi.exe when run as a stand alone. So now the problem appears to be getting NLog to find the config file because NLog cannot find the config file starting from the location of fsi.exe for Visual Studio. Looking at using NLog.dll.nlog in the NLog.dll directory.
The Problem
The problem with using NLog from F# Interactive is that NLog thinks that the Temp directory is where to find NLog.config and never succeeds. The way around this is to programmatically locate NLog.config for NLog.
Things to know to solve this problem:
When you run F# Interactive from within Visual Studio, it sets the current working directory to a temp file.
> System.Environment.CurrentDirectory;;
val it : string = "C:\Users\Eric\AppData\Local\Temp"
NLog logging requires three components:
a. reference to NLog.dll.
b. configuration file.
c. calls to a logger method from code.
NLog can be configured in many ways, both programmatically and using config files.
AppData is a hidden folder. Guess what that means when using Windows Explorer.
To get the location of the application with F# Interactive within Visual Studio you need __SOURCE_DIRECTORY__. See F# Spec 3.11 Identifier Replacements
NLog.conf can use a full file path. Obvious but necessary.
NLog file targets have an autoFlush option.
NLog can be installed into a Visual Studio project using NuGet.
Most of the info here comes from NLog Wiki.
Instead of jumping right into the F# Interactive solution, the following progression will be used because a DLL will need to be created to setup and hold the functions for use with NLog from F# Interactive.
Create a solution with three projects and install NLog.
Solution Name: NLogExample
Project 1 - Library, Name: Log - holds extension functions that call NLog
Project 2 - Library, Name: MyLibrary - used to generate a demo DLL that uses Log functions.
Project 3 - Console Application, Name: Main - used to generate a demo EXE that uses Log functions.
a. Manually create NLog.config
b. Access NLog.config from as a running project
c. Log a message to the file
a. Programmatically create a configuration
b. Create a configuration for a running project and log a message to the file
Create a configuration and log a message to the file using F# Interactive
1. Create a solution with three projects and install NLog
Using Visual Studio create the three projects.
Install NLog for all three projects.
2.a. Manually create NLog.config
Note: For these examples to work when __SOURCE_DIRECTORY__;; is run from F# Interactive it should report a directory that is part of the project and NOT the Temp directory.
Note: All the paths in this answer are relative to the solution directory.
When you see <Solution directory> substitute in your actual solution directory.
Path: <Solution director>\NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
throwExceptions="true">
<targets>
<target xsi:type="File"
name="file"
fileName="<Solution directory>\log.txt"
autoFlush="true"
/>
</targets>
<rules>
<logger name="*"
minlevel="Trace"
writeTo="file"
/>
</rules>
</nlog>
Note: Remember to change <Solution directory> to an actual path and set autoFlush="true"
Note: Adding NLog.config to the solution makes it easier to view/modify the file.
2.b. Access NLog.config from as a running project
In Log.Library1.fs
namespace Log
module MyLog =
let configureNLog () =
let projectPath = __SOURCE_DIRECTORY__
let soulutionPath = projectPath + "\.."
let configPath = soulutionPath + #"\NLog.config"
let xmlConfig = new NLog.Config.XmlLoggingConfiguration(configPath)
NLog.LogManager.Configuration <- xmlConfig
let NLogConfigToString () =
let targets = NLog.LogManager.Configuration.AllTargets
let out = ""
let out = Seq.fold (fun out target -> out + (sprintf "%A\n" target)) out targets
let rules = NLog.LogManager.Configuration.LoggingRules
let out = Seq.fold (fun out rule -> out + (sprintf "%A\n" rule)) out rules
out
let printNLogConfig () =
Printf.printfn "%s" (NLogConfigToString ())
and for the Log project add a reference to System.XML
In Main.Program.fs
open Log
[<EntryPoint>]
let main argv =
MyLog.configureNLog ()
MyLog.printNLogConfig ()
0 // return an integer exit code
and for the Main project add a reference to the Log project and set the Main project as the startup project.
When run this should output to the console:
File Target[file]
logNamePattern: (:All) levels: [ Trace Debug Info Warn Error Fatal ] appendTo: [ file ]
2.c. Log a message to the file
In Log.Library1.fs
namespace Log
open NLog
module MyLog =
let configureNLog () =
let projectPath = __SOURCE_DIRECTORY__
let soulutionPath = projectPath + "\.."
let configPath = soulutionPath + #"\NLog.config"
let xmlConfig = new NLog.Config.XmlLoggingConfiguration(configPath)
NLog.LogManager.Configuration <- xmlConfig
let NLogConfigToString () =
let targets = NLog.LogManager.Configuration.AllTargets
let out = ""
let out = Seq.fold (fun out target -> out + (sprintf "%A\n" target)) out targets
let rules = NLog.LogManager.Configuration.LoggingRules
let out = Seq.fold (fun out rule -> out + (sprintf "%A\n" rule)) out rules
out
let printNLogConfig () =
Printf.printfn "%s" (NLogConfigToString ())
let evalTracer = LogManager.GetLogger("file")
In Main.Program.fs
open Log
open Library1
[<EntryPoint>]
let main argv =
MyLog.configureNLog ()
MyLog.printNLogConfig ()
// Add as many of these as needed
MyLog.evalTracer.Trace("In Main #1.")
MyFunctions.test001 ()
0 // return an integer exit code
and for the Main project add a reference to the MyLibrary project.
In MyLibrary.Library1.fs
namespace Library1
open Log
module MyFunctions =
let test001 () =
MyLog.evalTracer.Trace("In Library #1.")
and for the MyLibrary project add a reference to the Log project.
When run the log file log.txt should contain something similar to:
2016-03-28 11:03:52.4963|TRACE|file|In Main #1.
2016-03-28 11:03:52.5263|TRACE|file|In Library #1
3.a. Programmatically create a configuration
If a NLog.config file exist delete it to verify that the code created a new configuration but did not create a file.
To set the configuration programmatically using F# you need to know:
This FileName string is a layout which may include instances of layout renderers. This lets you use a single target to write to multiple files.
SimpleLayout - Represents a string with embedded placeholders that can render contextual information.
To Log.Library1.fs add
let configureNLogPrgramatically () =
let config = new NLog.Config.LoggingConfiguration()
let fileTarget = new NLog.Targets.FileTarget()
let projectPath = __SOURCE_DIRECTORY__
let soulutionPath = projectPath + "\.."
let filePath = soulutionPath + #"\log.txt"
let layout = new NLog.Layouts.SimpleLayout(filePath)
fileTarget.Name <- "file"
fileTarget.FileName <- layout
fileTarget.AutoFlush <- true
config.AddTarget("file", fileTarget)
let rule1 = new NLog.Config.LoggingRule("*",NLog.LogLevel.Trace,fileTarget)
config.LoggingRules.Add(rule1)
NLog.LogManager.Configuration <- config
3.b. Create a configuration for a running project and log a message to the file
In Main.Program.fs
open Log
open Library1
[<EntryPoint>]
let main argv =
MyLog.configureNLogPrgramatically ()
MyLog.printNLogConfig ()
// Add as many of these as needed
MyLog.evalTracer.Trace("In Main #1.")
MyFunctions.test001 ()
0 // return an integer exit code
When run the log file log.txt should contain something similar to:
2016-03-28 11:16:07.2901|TRACE|file|In Main #1.
2016-03-28 11:16:07.3181|TRACE|file|In Library #1.
and note that a NLog.config file was NOT created.
4. Create a configuration and log a message to the file using F# Interactive
In MyLibrary.Script.fsx
// print out __SOURCE_DIRECTORY__ to make sure we are not using the Temp directory
printfn __SOURCE_DIRECTORY__
#I __SOURCE_DIRECTORY__
// Inform F# Interactive where to find functions in Log module
#I "../Log/bin/Debug/"
#r "Log.dll"
open Log
// Functions in Log module can now be run.
MyLog.configureNLogPrgramatically ()
MyLog.printNLogConfig ()
// Inform F# Interactive where to find functions in MyLibrary module
#I "../MyLibrary/bin/Debug/"
#r "MyLibrary.dll"
open Library1
// Functions in MyLibrary module can now be run.
MyFunctions.test001 ()
When the script is executed with F# Interactive
Microsoft (R) F# Interactive version 14.0.23413.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
>
<Solution directory>\MyLibrary
val it : unit = ()
--> Added <Solution directory>\MyLibrary' to library include path
--> Added <Solution directory>\MyLibrary\../Log/bin/Debug/' to library include path
--> Referenced <Solution directory>\MyLibrary\../Log/bin/Debug/Log.dll'
File Target[file]
logNamePattern: (:All) levels: [ Trace Debug Info Warn Error Fatal ] appendTo: [ file ]
--> Added <Solution directory>\MyLibrary\../MyLibrary/bin/Debug/' to library include path
--> Referenced <Solution directory>\MyLibrary\../MyLibrary/bin/Debug/MyLibrary.dll'
val it : unit = ()
>
The log file log.txt should contain something similar to:
2016-03-28 11:42:41.5417|TRACE|file|In Library #1.
Also, this will log while you still have an active F# Interactive session, so you can peek at the log between executing commands.

F# Module/Namespace Error

My first program with F#.
I have one file like so:
namespace LanguageMapper.Data
#if INTERACTIVE
#r "System.Data"
#r "System.Data.Linq"
#r "FSharp.Data.TypeProviders"
#endif
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
module Data =
// You can use Server Explorer to build your ConnectionString.
type SqlConnection = Microsoft.FSharp.Data.TypeProviders.SqlDataConnection<ConnectionString = #"connstring">
let db = SqlConnection.GetDataContext()
Then i have another file like so
namespace LanguageMapper.Program
open Data
module Program =
[<EntryPoint>]
let main argv =
let getLocale x =
match x with
| [|"live"|] -> "live"
| [|"dev"|] -> "dev"
| _ -> "local"
Over top of the open Data i get a red squiggly in VS telling me:
"Error 1 This declaration opens the namespace or module
'Microsoft.FSharp.Data' through a partially qualified path. Adjust
this code to use the full path of the namespace. This change will make
your code more robust as new constructs are added to the F# and CLI
libraries."
What am i doing wrong? I just want to reference one file from the other.
You need to open the module using its fully qualified name, that is including its namespace. So in LanguageMapper.Program you need to open LanguageMapper.Data.Data (only the last bit is the module name).
The Compiler is complaining on your open definition because it only specifies to open a namespace or module named Data - and it finds one in Microsoft.FSharp.Data, probably because there are some 'automatic' opens for the Microsoft.FSharp namespaces.

Resources