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
Related
I try to get the Z3 solver up and running in F#. So I created a fresh F# project in Visual Studio, added a reference to Microsoft.Z3.dll, and typed in the following code:
open Microsoft.Z3
let ctx = new Context()
let a = ctx.MkBoolConst("a")
Running this in the interactive window yields the following error:
System.InvalidCastException: Unable to cast object of type 'Microsoft.Z3.AlgebraicNum' to type 'Microsoft.Z3.BoolExpr'.
at Microsoft.Z3.Context.MkBoolConst(String name)
at <StartupCode$FSI_0013>.$FSI_0013.main#() in C:\Users\...\Program.fs:line 3
Stopped due to error
What am I missing?
This sounds very much like https://github.com/Z3Prover/z3/issues/1882
You might have to recompile/reinstall. Follow the instructions in that ticket.
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=','))
I'm trying to explain a weird F# compiler behavior between Release and Debug configurations regarding transitive dependencies. I will use Newtonsoft.Json package as the base dependency here, because that's the furthest I managed to get in pinpointing the issue, and it makes the example a bit less abstract.
Let's create a library project called SerializerProject, referencing Newtonsoft.Json via paket. In this project there is only one module:
module Serializer =
open System.IO
open System.Text
open Newtonsoft.Json
type OptionConverter() =
inherit JsonConverter()
(* only the signature is important, the implementation
and other methods are not interesting *)
override x.WriteJson(writer: JsonWriter, value: obj, serializer: JsonSerializer) =
(* ... *)
let fromJson<'a> (bytes: byte []): 'a =
let s = Encoding.UTF8.GetString(bytes)
use sr = new StringReader(s)
use jr = new JsonTextReader(sr)
let serializer = JsonSerializer()
serializer.Converters.Add(OptionConverter())
serializer.Deserialize<'a>(jr)
Now let's create a second project in the same solution and reference SerializerProject via project reference. I'd like to use fromJson in my new project, that's why I referenced SerializerProject in the first place.
module MyModule =
open Serializer
(* This is here just so we reference the fromJson function *)
let deserializer bytes = fromJson bytes
This is the minimal example to reproduce the behavior.
Now when I build the solution in Debug configuration, everything compiles and works fine. But when I switch to Release, the compilation fails in the second project, in MyModule in the deserializer definition. The exact error message is this:
The type referenced through 'Newtonsoft.Json.JsonWriter' is defined in an assembly that is not referenced. You must add a reference to assembly 'Newtonsoft.Json'
I'm using Visual Studio 2015 Update 3, F# tools (fsc, fsi) show version 14.0.23413.0.
It kind of makes sense, because it's reading metadata of the SerializerProject and finds that public OptionConverter type leaks the type JsonWriter on its public WriteJson method (as well as other types and other methods, but this one is encountered first), but what makes me wonder is why this works in Debug mode and is only a problem in the Release mode.
What kind of extra operations does the compiler do that affect this?
Why is this not a problem in Debug build when the type defined in Newtonsoft.Json really leaks transitively into the second project?
As suggested in the comments I tried referencing Newtonsoft.Json and decompiling the second assembly with ILSpy to see whether inlining turned on by compiler optimizations is to blame here, but even in Release configuration the second assembly looks like this:
call !!0 [SerializerProject]Serializer::fromJson<!a>(uint8[])
The fromJson function has not been inlined to expose the JsonWriter type directly, so there seem to be something more subtle going on.
This isn't a blocking issue, I just made the converter types private as I don't want to use them from the outside anyway, but I'd like to dig deeper in F# compiler inner workings.
I am working ti old F# code from Expert F#. However, the example doesn't build anymore.
The following two calls don't seem to exist:
semaphore.AsyncWaitOne(?millisecondsTimeout=timeout)
and
reader.ReadToEndAsync()
Does anyone know what these have been replaced with or if I am just missing a reference?
It's now called Async.AwaitWaitHandle.
AsyncReadToEnd is in the F# PowerPack.
By now, FSharp PowerPack project has been broken up into smaller modules for any further development.
Specifically, the AsyncStreamReader class and the extension methods for the reading from a StreamReader, WebClient, etc. the new project is FSharpx.Async.
1) AsyncWaitOne is now called Async.AwaitWaitHandle.
2) AsyncReadToEnd() extension method does not exists anymore in the FSharp.PowerPack.
It has been replaced with the AsyncStreamReader dedicated type that contains proper asynchronous implementation of stream reading (like ReadToEnd, ReadLine, etc.)
It can be used like that:
async {
use asyncReader = new AsyncStreamReader(stream)
return! asyncReader.ReadToEnd() }
Note: Once you have installed FSharp.PowerPack, the AsyncStreamReader type will be 'injected' in the Microsoft.FSharp.Control namespace
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 ?