Defining unit of measure in F# signature file - f#

Is it possible to define a Unit of Measure in a signature file (.fsi)?
I have tried to add it after namespace definition,
[<Measure>] type unitOfMeasure
but the compiler complains "type unitOfMeasure is not defined". I need to re-define it in the implementation file (.fs).

I think the reason might be that Units of Measure are not public visible (for the CLR) - they get erased after/while compilation

Related

Get type of a module at compile time in F#

We know that in C# we can get type of a type at compile time using typeof(OutType) this lets us pass this to attributes later as it is constant expression.
I saw this question, but it doesn't really address the compile time usage.
So my question is: Is there a way to get System.Type of a given module at compile type within F# standard library?
F# disallows obtaining a module's type using its typeof operator by design, as they're not first-class concepts in the language.
From the spec, section 13.2:
F# modules are compiled to provide a corresponding compiled CLI type declaration and
System.Type object, although the System.Type object is not accessible by using the typeof
operator.
Modules compile to static classes however, so it is possible to obtain the type at runtime using reflection (and that's what happens in typeof<MyModule.Dummy>.DeclaringType example), and it's possible to obtain the type of a module defined in a referenced F# assembly using typeofoperator in C#.
For what you're trying to do, you'd best use a class instead of a module, because then you can get hold of the type without hassle:
type MyFactoryClass =
static member TestCases = [ 1; 2; 3 ]
...
[<Test; TestCaseSource(typeof<MyFactoryClass>, "TestCases">]
let test (arg: int) = ...
If you are OK to refer to a type inside that module (or create a dummy one if there are no types), you could do this:
module MyModule =
type Dummy = Dummy
let myModule = typeof<MyModule.Dummy>.DeclaringType

Passing "unit" as type parameter to generic class in F#

I have an interface which takes a generic parameter and has an abstract method
type MyInterface<'a> =
abstract member abstractMethod: 'a -> 'a
...and I have a derived class which inherits from base class using unit for the type parameter
type Derived() =
interface MyInterface<unit> with
override this.abstractMethod (_) = ()
but the compiler complains that
Error The member 'abstractMethod : unit -> unit' does not have the
correct type to override the corresponding abstract method.
If I use another type instead of unit, int for example, the code compiles.
Is this a bug in the compiler? Is there a workaround for it?
Thanks!
unit is "special" in terms of interop: when a function takes a unit as parameter, it is compiled to IL as a parameterless function, and when a function returns a unit as result, it is compiled as a void function. As a result of this trickery, you can't really use unit as a "general-purpose" type in interop settings (such as classes and interfaces).
In fact, when I try to compile your code on my machine, I get a different error:
The member 'abstractMethod : unit -> unit' is specialized with 'unit'
but 'unit' can't be used as return type of an abstract method
parameterized on return type.
Which is trying to say roughly what I described above.
(I'm not sure why you're getting what you're getting; perhaps you're using an older version of F#)

MapTo for SqlProvider: no compile check for type mismatch

I'm trying to use the SQL Type Provider and I'm following the approach suggested in the guidelines.
Compile vs runtime errors
I've noticed that the .MapTo<'T> convenience method is introducing runtime type-cast exceptions instead of anticipating the type checks at compile time.
Let's say we have a generic
let sel = r.MapTo<Selection>()
and compare the above with a simpler, but longer property by property assignment
sel.PacketNum <- r.PacketNum
In the latter case I get a safer and more helpful compile error, like for example:
error FS0001: This expression was expected to have type int but here has type int64
Am I missing something about the .MapTo<'T> behaviour at compile vs runtime? Is this done by or against design?
Fluent mapping and DB type assignment
I also wonder if there is the possibility (other frameworks provide such features) to
set the mapping with a property attribute or similar (what if the column name is packets instead of packet_num)?
set a different correspondence between a .Net type and a DB type (INTEGER to int instead of INT to int)?
or why it is not needed

How to initialize Type int()?

When trying to initialize a Type to \int(), as found in http://tutor.rascal-mpl.org/Rascal/Libraries/analysis/m3/Core/modifiers/modifiers.html#/Rascal/Libraries/lang/java/m3/AST/Declaration/Declaration.html , rascal throws an error saying "Expected Type, but got TypeSymbol".
This is the code I used:
Type inttype = \int();
What is the proper way to initialize a Type variable to \int()?
To solve the problem you can write:
Type myIntType = Type::\int();
More explanation follows. The \int() constructor is defined at least twice in different places:
In the abstract syntax tree definition of Java types that are used in Declarations. It is the representation of the word int in source code.
In the TypeSymbol definition in java::lang::m3::Core. There \int() represents a symbolic type.
They have the same name because they point to the same concept, but in different representations. The first is just used for a direct representation of source code, the second is used for its abstract symbolic interpretation.
To distinguish between the two representations you should either import the module that defines the AST nodes, or import the module that defines the TypeSymbols. If you happen to have both imported, you should choose a representation explicitly:
Type myIntType = Type::\int();
TypeSymbol mySymbol = TypeSymbol::\int();
So to finally explain the error message, the system chose the second kind of \int()` in TypeSymbol to build a value, and you tried to assigned it to a variable of the first kind.
\int() is a TypeSymbol, I think you're looking for
Type inttype = int();

Namespace aliasing in F#?

I have a name clashing problem while opening some .Net assemblies in my F# code using
open System.IO
The only option I found and use now is to provide the full names of types for conflicting types, but this is a little bit boring.
Is there any possibility to define an alias for .Net namespace in F# to prevent name clashing?
F# does not support aliasing of namespaces - only modules and types. So, to resolve the conflicts between .NET assemblies, you will, unfortunatelly, need to define aliases for all the types you're using.
This may be slightly easier thanks to the fact that F# type aliases are viewed as normal type declarations (by the F# compiler, not by the runtime). This means that, unlike with C# using keyword, you can define them in a spearate file:
// Aliases.fs
namespace SysIO
// Open the 'System' namespace to get a bit shorter syntax
// ('type File = File' is interpreted as discriminated union)
open System
type File = IO.File
type Directory = IO.Directory
In the rest of your application, you can now use SysIO.File. You still have to write the aliases, but at least you don't have to do that in every file...

Resources