Simple correct implementation file in verbose syntax? - f#

UPDATE
The general question is: how to use verbose syntax of F# correctly? Verbose syntax is the syntax which is close to OCaml syntax, i.e. syntax with many commas etc.
OLD TEXT
I want to turn light syntax off in F# to have verbose syntax which is closer to OCaml.
I wrote the following code
#light "off"
let k=3.14;;
and got an error on let:
Unexpected keyword 'let' or 'use' in implementation file
What is correct implementation file structure without light syntax?

The problem is that you have written this inside a .fsi file - which is an FSharp Interface definition file; it has nothing to do with fsi.exe (FSharp Interactive).
The message "Unexpected keyword 'let' or 'use' in implementation file" is a tell - interface definitions were expected. Simply use a .fs extension.
If you want reuse ML code, consider changing the file extension to .ml, and add a #nowarn "62" directive at the beginning to ignore the legacy warning.
#nowarn "62"
#light "off"
let div2 = 2;;
let f x =
let r = x % div2 in
if r = 1 then
begin "Odd" end
else
begin "Even" end

I don't see anything wrong but... why the two ;? Are you compiling it or running in fsi?

Related

F# FSI "Unexpected compiler generated literal in interaction" with "#I __SOURCE_DIRECTORY__"

If I create a new F# file 'Test.fsx' in VSCode with the line
#I __SOURCE_DIRECTORY__
attempting to run the code in FSI generates the error
Test.fsx(2,4): error FS0010: Unexpected compiler generated literal in interaction. Expected incomplete structured construct at or before this point, ';', ';;' or other token.
Any idea what might be going wrong?
It is a known issue in VS2019, which has been fixed in VS2022.
https://github.com/dotnet/fsharp/issues/13467
You may replace the code with
#I "."

Am I using TextLoader wrong when running the ML.Net Iris demo in F#?

I am new to F#/.NET and I am trying to run the F# example provided in the accepted answer of How to translate the intro ML.Net demo to F#? with the ML.NET library, using F# on Visual Studio, using Microsoft.ML (0.2.0).
When building it I get the error error FS0039: The type 'TextLoader' is not defined.
To avoid this, I added the line
open Microsoft.ML.Data
to the source.
Then, however, the line
pipeline.Add(new TextLoader<IrisData>(dataPath,separator = ","))
triggers:
error FS0033: The non-generic type 'Microsoft.ML.Data.TextLoader' does not expect any type arguments, but here is given 1 type argument(s)
Changing to:
pipeline.Add(new TextLoader(dataPath,separator = ","))
yields:
error FS0495: The object constructor 'TextLoader' has no argument or settable return property 'separator'. The required signature is TextLoader(filePath: string) : TextLoader.
Changing to:
pipeline.Add(new TextLoader(dataPath))
makes the build successful, but the code fails when running with
ArgumentOutOfRangeException: Column #1 not found in the dataset (it only has 1 columns), I assume because the comma separator is not correctly picked up (incidentally, you can find and inspect the iris dataset at https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data).
Also
pipeline.Add(new TextLoader(dataPath).CreateFrom<IrisData>(separator: ','))
won't work.
I understand that there have been changes in TextLoader recently (see e.g. https://github.com/dotnet/machinelearning/issues/332), can somebody point me to what I am doing wrong?
F# just has a bit of a different syntax that can take some getting used to. It doesn't use the new keyword to instantiate a new class and to use named parameters it uses the = instead of : that you would in C#.
So for this line in C#:
pipeline.Add(new TextLoader(dataPath).CreateFrom<IrisData>(separator: ','))
It would be this in F#:
pipeline.Add(TextLoader(dataPath).CreateFrom<IrisData>(separator=','))

F# integer file directive

I've been using fslex and fsyacc, and the F# source files (.fs they generate from the lexer (.fsl) and parser (.fsp) rules refer to the original .fsl (and sometimes to the same .fs source file) all over the place with statement such as this (numbers are line numbers):
lex.fs
1 # 1 "/[PROJECT-PATH-HERE]/lex.fsp
...
16 # 16 "/PROJECT-PATH-HERE]/lex.fs
17 // This is the type of tokens accepted by the parser
18 type token =
19 | EOF
...
Also, the .fs files generated by pars.fsp do the same kind of thing, but additionaly reference to the F# signature file (.fsi) generated alongside it. What does any of this do/mean?
The annotations you see in the generated code are F# Compiler Directives (specifically, the 'line' directive).
The 'line' directive makes it so that when the F# compiler needs to emit a warning/error message for some part of the generated code, it has a way to determine which part of the original file corresponds to that part of the generated code. In other words, the F# compiler can generate a warning/error message referencing the original code which is the basis of the generated code causing the error.

ComImport in F#

I'm trying to translate some code from C# to F#, specifically the code to create a shortcut, from here: http://vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects/Creating_and_Modifying_Shortcuts/ShellLink_Code_zip_ShellLink/ShellLink_cs.asp
The code in C# reads:
[GuidAttribute("00021401-0000-0000-C000-000000000046")]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
[ComImportAttribute()]
private class CShellLink{}
Which I translated to F# as:
[<GuidAttribute("00021401-0000-0000-C000-000000000046")>]
[<ClassInterfaceAttribute(ClassInterfaceType.None)>]
[<ComImportAttribute()>]
type CShellLink() = class end
Unfortunately, when I switch to the F# implementation, I get a runtime error of: "Method with non-zero RVA in an Import". This seems to be the same error as reported here: http://social.msdn.microsoft.com/Forums/en-US/fsharpgeneral/thread/dada2004-5218-4089-8918-eed2464bbbcd
Is there any workaround? I'm trying to port the application to only use F#, so if this can't be written in F# that project is going to have to be rethought.
this looks like a limitation in F# compiler: it cannot define existing COM classes using ComImportAttribute, it only works for interfaces. Can you use this as workaround?
let shellLink =
let ty = System.Type.GetTypeFromCLSID (System.Guid "00021401-0000-0000-C000-000000000046")
Activator.CreateInstance ty

FsLex changed with latest PowerPack?

I've been working on a compiler for a while but after changing to PowerPack 1.9.9.9 and the release version of VS2010 I'm no unable to compile the following line:
let lexbuf = Lexing.from_string text
I get the following two error:
"The value, constructor, namespace or type 'from_string' is not defined" pretty obviopus what it's trying to tell me but what's the resolution?
My quick guess is that this function has been renamed to fromString (because, in general, functions with underscores such as of_seq are now written in camelCase).
Lexing.LexBuffer<_>.FromString ?

Resources