F# CsvProvider cant find member in Row error FS0039 - f#

I try example from Isaac Abraham book "get programming with F#". In it I simply import csv file into F# script and try to do simple operations.
#r "nuget: FSharp.Data"
open FSharp.Data
type Football = CsvProvider<"FootballResults.csv">
let data = Football.GetSample().Rows|> Seq.toArray
let work = data |> Seq.filter (fun i -> i.``Full Time Away Goals`` > i.``Half Time Away Goals``)
let print = work |> Seq.take 10 |> Seq.map (fun i -> i.``Half Time Home Goals``)
let print2 = print |> Seq.iter (fun i -> printfn "%i" i)
I get an error:
script.fsx(6,43): error FS0039: The type 'Row' does not define the field, constructor or member 'Full Time Away Goals'.
I am pretty much stuck here. Csv file is from here and I can see fields name in intellisense window, but no matter what I try, I cant do any work with fields.
I use VsCode with
Microsoft (R) F# Interactive version 11.0.0.0 for F# 5.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
Update:
I used absolute path and it worked; but I must say I have script and csv file in same directory.
Directory of C:\study\fsharp_Study\csv
20.01.2021 15:20 <DIR> .
20.01.2021 15:20 <DIR> ..
20.01.2021 15:19 26 446 FootballResults.csv
21.01.2021 08:29 373 script.fsx
2 File(s) 26 819 bytes
2 Dir(s) 131 790 934 016 bytes free

The problem is that F# can't find "FootballResults.csv" at runtime, because it's located in a different directory from the one that the script is running in. The easiest way to solve this is to specify the full path to the .csv file:
type Football = CsvProvider<"C:\My\Full\Path\FootballResults.csv">

Related

How to traverse String[][] in F#

Context: Microsoft Visual Studio 2015 Community; F#
I've been learning F# for about 1/2 a day. I do have a vague idea of how to do functional programming from a year spent fiddling with mLite.
The following script traverses a folder tree and pulls in log files. The files have entries delimited by ~ and there may be one or more there.
open System
open System.IO
let files =
System.IO.Directory.GetFiles("C:\\scratch\\snapshots\\", "*.log", SearchOption.AllDirectories)
let readFile (file: string) =
//Console.WriteLine(file)
let text = File.ReadAllText(file)
text
let dataLines (line: string) =
line.Split('~')
let data =
files |> Array.map readFile |> Array.map dataLines
So at this point data contains a String[][] and I'm at a bit of a loss to figure out how to turn it into a String[], the idea being that I want to convert all the logs into one long vector so that I can do some other transformations on it. For example, each log line begins with a datetime so having turned it all into one long list I can then sort on the datetime.
Where to from here?
As stated in the comments, you can use Array.concat :
files |> Array.map readFile |> Array.map dataLines |> Array.concat
Now some refactoring, the composition of two maps is equivalent to the map of the composition of both functions.
files |> Array.map (readFile >> dataLines) |> Array.concat
Finally map >> concat is equivalent to collect. So your code becomes:
files |> Array.collect (readFile >> dataLines)

referencing one's own class library in a F# project on VS2015

i have a solution called Algos
on Solution explorer i have 2 projects inside this solution
one called Algos (again ! maybe i should change the name for avoiding confusion ?)
which is a console application
one called MyLibrary which is a Class Library
I have in the solution explorer added in the References of the Project Algo MyLibrary and i can see it in the list.
// useful functions
// returns the minimum + index of the minimum
namespace Misc
exception InnerError of string
module Search =
let mini (s : (int*int) list) =
match s with
| [] -> (-1,(-1,-1))
| _ -> s |> Seq.mapi (fun i x -> (i, x)) |> Seq.minBy snd
let maxi (s : (int*int) list) =
match s with
| [] -> (-1,(-1,-1))
| _ -> s |> Seq.mapi (fun i x -> (i, x)) |> Seq.maxBy snd
module Bit =
let rec sumbits (n:int):int=
let rec helper acc m =
match m with
| 0 -> acc
| 1 -> acc+1 // enlever cela ?
| _ -> let r = m%2
helper (acc+r) (m>>>1)
helper 0 n
let power2 k =
let powers_of_2 = [|1;2;4;8;16;32;64;128;256;512;1024;2048;4096;8192;16384;32768;65536;131072;262144;524288;1048576;2097152;4194304;8388608;16777216|]
if ((k >= 24) || (k<0)) then raise (InnerError("power exponent not allowed"))
else powers_of_2.[k]
i'm just to use Misc.Bit.power2 in the main code
open MyLibrary
let a = Misc.Bit.power2 3
but Misc.Bit will be underlined and I have a compiler error
Severity Code Description Project File Line Suppression State
Error The value, constructor, namespace or type 'Bit' is not defined Algos C:\Users\Fagui\Documents\GitHub\Learning Fsharp\Algos\Algos\TSP.fs 50
what have i done wrong ? does it come from other parts of the source code perhaps ?
there are no other warnings.
both projects use .NET Framework 4.5.2
MyLibrary uses Target F# Runtime 4.3.1 while there is no similar indication for Algos.
thanks
Two things come to mind here: I don't see where the namespace MyLibrary is defined, and you haven't mentioned that you actually compiled the dependency.
Generally, to reference and use a library within the same solution, you need to:
add the library to the using program's dependency, preferably via: References – right-click – add Reference (Reference Manager) – Projects – Solution, by checking the checkbox of the dependency.
compile the dependency. When referenced properly, this should automatically occur before dependent code is compiled, but IntelliSense will only update after compiles! So hit compile when you see outdated errors.
use identifiers from the library via their correct namespace. Make sure that the qualified names or open declarations in the using code are correct.
To my knowledge, this should be all you need to do.
There are rare cases where files get write-locked but never released on compilation and you need to restart Visual Studio to be able to compile again. I've also encountered a case where some interaction of Git and Visual Studio created corrupted, half-deleted files with effectively no file owner; this required a reboot to fix. If you're really scratching your head and the errors are clearly nonsensical, maybe try moving the folder to check for file system damage.
This should certainly work. Please also make sure that you target same versions of F# and .NET: .NET 4.5.2 and 4.4.0.0 in the library and the console application

Problems launching functions using continuation in Visual Studio

I'm currently trying to learn f# using the book Real-World Functional Programming by Petricek and Skeet (2010) but have been encountering problems when using continuations to avoid stack overflow.
The problem that I have been encountering is that my code using continuations works perfectly when launched in the f# interactive, but still causes stack overflow when placing the code in the program.fs file and then launching it through the debugger in Visual Studio.
It is unclear to me why this happens, and would very much appreciate if anyone could give me an explanation to why this happens.
In case the version of Visual Studio is relevant, I am using:
Visual Studio Ultimate 2012
Version 11.0.61030.00 Update 4
The .Net framework used is:
Version. 4.5.51641
The code presented in the book that is causing this problem is presented below:
open System
let rand = new Random()
//A tree is either a leaf with a value or a node that contains two children
type IntTree =
| Leaf of int
| Node of IntTree * IntTree
//A list of that will decide all leaf values
let numbers2 = List.init 1000000 (fun _ -> rand.Next(-50,51))
///Creates an imbalanced tree with 1000001 leafs.
let imbalancedTree2 =
numbers2 |> List.fold (fun currentTree num ->
Node(Leaf(num), currentTree)) (Leaf(0))
//Sums all leafs in a tree by continuation and will execute the inserted function with the total
//sum as argument once all values have been summed.
let rec sumTreeCont tree cont =
match tree with
| Leaf(num) -> cont(num)
| Node(left, right) ->
sumTreeCont left (fun leftSum ->
sumTreeCont right (fun rightSum ->
cont(leftSum + rightSum)))
//Sums the imbalanced tree using the sumTreeCont function
let sumOfTree = sumTreeCont imbalancedTree2 (fun x -> x)
Thanks in advance!
//Tigerstrom
If you are running the program in Debug mode, then the default Visual Studio project setting disables tail calls. The main reason is that, with tail calls enabled, you do not get very useful information in the call stack (which makes debugging harder).
To fix this, you can go to your project options and check "Generate tail calls" on the "Build" page. In release mode, this is enabled by default.

F# RX Sum of 1 to 100 code sample

I am learning RX (Reactive Extensions), I tried to use some code samples from internet, the source code was in C#:
var input = Observable.Range(1, 100);
input.Sum().Subscribe(x => Console.WriteLine("The Sum is {0}", x));
Since I don't really "SPEAK" C#, so I want to use F# to do the same thing.
I download RX, and create a F# windows application, add reference to System.Reactive. My IDE is VS 2010 Ultimate, RX version is: 1.1.11111
Here is my code:
#light
open System
open System.Collections.Generic
open System.ComponentModel
open System.Linq
open System.Text
open System.Reactive
open System.Reactive.Linq
let input = Observable.Range(1, 100)
let x = input.Sum().Subscribe()
printfn "%A" x
The result should be 5050, as the sum of 1 to 100 is 5050. However, I can see only this:
System.Reactive.AutoDetachObserver`1[System.Int32]
Please let me know how I can see the result for 5050.
I hope the C# code will work in F# too. If not, please let me know what I can do.
Thanks and Happy New Year to you all!
The Subscribe method takes a function as its argument (x => foo is an anonymous function (lambda expression) in C#). So you should also call it with a function as its argument:
let input = Observable.Range(1, 100)
input.Sum().Subscribe(fun x -> printfn "%A" x)
Or
let input = Observable.Range(1, 100)
input.Sum().Subscribe(printfn "%A")

Useful F# Scripts

I have been investigating the use of F# for development and have found (for my situations) building scripts to help me simplify some complex tasks is where I can get value from it (at the moment).
My most common complex task is concatenating files for many tasks (mostly SQL related).
I do this often and every time I try to improve on my F# script to do this.
This is my best effort so far:
open System.IO
let path = "C:\\FSharp\\"
let pattern = "*.txt"
let out_path = path + "concat.out"
File.Delete(out_path)
Directory.GetFiles(path, pattern)
|> Array.collect (fun file -> File.ReadAllLines(file))
|> (fun content -> File.WriteAllLines(out_path, content) )
I'm sure others have scripts which makes their sometimes complex/boring tasks easier.
What F# scripts have you used to do this or what other purposes for F# scripts have you found useful?
I found the best way for me to improve my F# was to browse other scripts to get ideas on how to tackle specific situations. Hopefully this question will help me and others in the future. :)
I have found an article on generating F# scripts that may be of interest:
http://blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx
I use F# in a similar way when I need to quickly pre-process some data or convert data between various formats. F# has a great advantage that you can create higher-order functions for doing all sorts of similar tasks.
For example, I needed to load some data from SQL database and generate Matlab script files that load the data. I needed to do this for a couple of different SQL queries, so I wrote these two functions:
// Runs the specified query 'str' and reads results using 'f'
let query str f = seq {
let conn = new SqlConnection("<conn.str>");
let cmd = new SqlCommand(str, conn)
conn.Open()
use rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
while rdr.Read() do yield f(rdr) }
// Simple function to save all data to the specified file
let save file data =
File.WriteAllLines(#"C:\...\" + file, data |> Array.ofSeq)
Now I could easily write specific calls to read the data I need, convert them to F# data types, does some pre-processing (if needed) and print the outputs to a file. For example for processing companies I had something like:
let comps =
query "SELECT [ID], [Name] FROM [Companies] ORDER BY [ID]"
(fun rdr -> rdr.GetString(1) )
let cdata =
seq { yield "function res = companies()"
yield " res = {"
for name in comps do yield sprintf " %s" name
yield " };"
yield "end" }
save "companies.m" cdata
Generating output as a sequence of strings is also pretty neat, though you could probably write a more efficient computation builder using StringBuilder.
Another example of using F# in the interactive way is described in my functional programming book in Chapter 13 (you can get the source code here). It connects to the World Bank database (which contains a lots of information about various countries), extracts some data, explores the structure of the data, convert them to F# data types and calculates some results (and visualizes them). I think this is (one of many) kinds of tasks that can be very nicely done in F#.
Sometimes if I want a brief of an XML structure (or have a recursive list to use in other forms such as searches), I can print out a tabbed list of nodes in the XML using the following script:
open System
open System.Xml
let path = "C:\\XML\\"
let xml_file = path + "Test.xml"
let print_element level (node:XmlNode) = [ for tabs in 1..level -> " " ] # [node.Name]
|> (String.concat "" >> printfn "%s")
let rec print_tree level (element:XmlNode) =
element
|> print_element level
|> (fun _ -> [ for child in element.ChildNodes -> print_tree (level+1) child ])
|> ignore
new XmlDocument()
|> (fun doc -> doc.Load(xml_file); doc)
|> (fun doc -> print_tree 0 doc.DocumentElement)
I am sure it can be optimised/cut down and would encourage by others' improvements on this code. :)
(For an alternative snippet see the answer below.)
This snippet transforms an XML using an XSLT. I wasn't sure of hte best way to use the XslCompiledTransform and XmlDocument objects the best in F#, but it seemed to work. I am sure there are better ways and would be happy to hear about them.
(* Transforms an XML document given an XSLT. *)
open System.IO
open System.Text
open System.Xml
open System.Xml.Xsl
let path = "C:\\XSL\\"
let file_xml = path + "test.xml"
let file_xsl = path + "xml-to-xhtml.xsl"
(* Compile XSL file to allow transforms *)
let compile_xsl (xsl_file:string) = new XslCompiledTransform() |> (fun compiled -> compiled.Load(xsl_file); compiled)
let load_xml (xml_file:string) = new XmlDocument() |> (fun doc -> doc.Load(xml_file); doc)
(* Transform an Xml document given an XSL (compiled *)
let transform (xsl_file:string) (xml_file:string) =
new MemoryStream()
|> (fun mem -> (compile_xsl xsl_file).Transform((load_xml xml_file), new XmlTextWriter(mem, Encoding.UTF8)); mem)
|> (fun mem -> mem.Position <- (int64)0; mem.ToArray())
(* Return an Xml fo document that has been transformed *)
transform file_xsl file_xml
|> (fun bytes -> File.WriteAllBytes(path + "out.html", bytes))
After clarifying approaches to writing F# code with existing .net classes, the following useful code came up for transforming xml documents given xsl documents. The function also allows you to create a custom function to transform xml documents with a specific xsl document (see example):
let transform =
(fun xsl ->
let xsl_doc = new XslCompiledTransform()
xsl_doc.Load(string xsl)
(fun xml ->
let doc = new XmlDocument()
doc.Load(string xml)
let mem = new MemoryStream()
xsl_doc.Transform(doc.CreateNavigator(), null, mem)
mem
)
)
This allows you to transform docs this way:
let result = transform "report.xml" "report.xsl"
or you can create another function which can be used multiple times:
let transform_report "report.xsl"
let reports = [| "report1.xml"; "report2.xml" |]
let results = [ for report in reports do transform_report report ]

Resources