Simple type test in F# - f#

I've been googling for a while now... Ok, I'm sorry, this one is pathetically easy but is there an operator in F# to compare class types, like the 'is' keyword in C#? I don't want to use a full blown match statement or start casting things. Cheers

You can use the :? construct both as a pattern (inside match) or as an operator:
let foo = bar :? System.Random
This behaves slightly differently than in C#, because the compiler still tries to do some checks at compile-time. For example, it is an error to use this if the result would be surely false:
let bar = 42
let foo = bar :? System.Random // Error
I don't think this could lead to confusion, but you can always add box to convert the argument to obj, which can be tested against any type:
let foo = box bar :? System.Random

If you want a general C#-to-F# quick-reference, see
http://lorgonblog.wordpress.com/2008/11/28/what-does-this-c-code-look-like-in-f-part-one-expressions-and-statements/
which answers this question and many others.

Related

F# operator overloading strange behavoir

Let's say that for some strange reason I want to have this function:
let (~-) (str:string) = 42
So I can do something like this and get 42 as result:
-"test"
val it : int = 42
Which is fine. But now when I do:
let a = 100
-a
I get:
error FS0001: This expression was expected to have type
string
but here has type
int
Any idea why is this happening?
When you define operators using let, the new definition hides all previous definition of the operator. So in your example, you are hiding the default implementation of the unary minus (which works for numbers) and replacing it with a new operator that only works on strings.
It is not easy to re-define overloaded operators on built-in types. If you need that, it is probably better idea to avoid using operators (just use a function). However, if you want to provide an overloaded operator for a custom type, you can do this by adding operator as a static member:
type MinusString(s:string) =
member x.Value = s
/// Provide unary minus for MinusString values
static member (~-) (ms:MinusString) =
MinusString("-" + ms.Value)
-(MinusString "hi") // Returns "-hi"
If you really want to redefine built-in operator like unary minus and make it work on string, then there is actually a way to do this using a trick described in earlier SO answers. However, I would only use this if you have a good reason.
Simply, you overwrote the minus operator with one that takes a string and returns an int, then tried to apply it to an int, which it can't do anymore.

What's with "Uppercase variable identifiers should not generally be used in patterns..."?

This compiler like:
let test Xf Yf = Xf + Yf
This compiler no like:
let test Xfd Yfd = Xfd + Yfd
Warning:
Uppercase variable identifiers should not generally be used in patterns, and may indicate a misspelt pattern name.
Maybe I'm not googling properly, but I haven't managed to track down anything which explains why this is the case for function parameters...
I agree that this error message looks a bit mysterious, but there is a good motivation for it. According to the F# naming guidelines, cases of discriminated unions should be named using PascalCase and the compiler is trying to make sure that you don't accidentally misspell name of a case in pattern matching.
For example, if you have the following union:
type Side =
| Left
| Right
You could write the following function that prints "ok" when the argument is Left and "wrong!" otherwise:
let foo a =
match a with
| Lef -> printfn "ok"
| _ -> printfn "wrong!"
There is a typo in the code - I wrote just Lef - but the code is still valid, because Lef can be interpreted as a new variable and so the matching assigns whatever side to Lef and always runs the first case. The warning about uppercase identifiers helps to avoid this.
F# tries to enforce case rules for active patterns - consider what does this code do
let f X =
match X with
|X -> 1
|_ -> 2
This is quite confusing. Also, function parameters are similar to patterns, you can do
let f (a,b,_) = a,b
for example. Not quite sure why the third letter triggers the warning though

Nullablle<>'s and "null" in F#

I'm calling functions in the XNA framework from F# that accept Nullable values. Now, in C#, you would just call:
foo(arg1, arg2, null, arg4)
Now, I tried that in F#, but it doesn't like it. It says: "Error 9 Type constraint mismatch. The type 'a is not compatible with type System.Nullable The type 'System.Nullable' does not have 'null' as a proper value."
I understand why this is happening, sort of, but it seems really inconvenient. All I'm doing now is, to make life easier, instead of repeatedly typing (Nullable<Rectangle>)null everytime I call the function, I just did let nullRect = (Nullable<Rectangle>)null, and use nullRect. This seems really stupid, especially since I'd have to do that for every nullable type I interact with. Is there a better, more idiomatic way to handle this?
Here's what I'd do:
[<GeneralizableValue>]
let nl<'a when 'a : struct
and 'a : (new : unit -> 'a)
and 'a :> System.ValueType> : System.Nullable<'a> =
unbox null
Now you can use nl wherever you would have used null before.
EDIT
As Tomas notes, this can be written much more concisely as:
let nl = System.Nullable<_>()
If you don't want to use kvb's very clever answer, in many cases you can omit the specific type and just use Nullable<_>() - F# can infer what sort of Nullable you mean.

Questions about the definition of lazy

On line 5633 in prim-types.fs (v1.9.7.8) there is the following type abbreviation:
type 'T ``lazy`` = Lazy<'T>
I have a few questions about it.
What do the double backticks mean?
Is this definition equivalent to type lazy<'T> = Lazy<'T>? (If not, how is it different?)
The double back ticks are a way of allowing an F# keyword to be used as an identifier. Another example would be
let ``let`` = 42
To answer the second half of your question, generic types in F# can be specified using either the O'Caml-style syntax where the generic parameter precedes the type (e.g 'a list, int array, etc.), or the .NET-style with angle brackets (e.g. list<'a>, array<int>, etc.), so the two definitions are indeed basically equivalent (except that your version as written is syntactically invalid because lazy is a keyword). For multi-parameter generic types, the O'Caml style is deprecated and will generate a warning (e.g. let (m:(int,string) Map) = Map.empty should be rewritten as let (m:Map<int,string>) = Map.empty).

Point-free style with objects/records in F#

I'm getting stymied by the way "dot notation" works with objects and records when trying to program in a point-free functional style (which I think is a great, concise way to use a functional language that curries by default).
Is there an operator or function I'm missing that lets me do something like:
(.) object method instead of object.method?
(From what I was reading about the new ? operator, I think it works like this. Except it requires definition and gets into the whole dynamic binding thing, which I don't think I need.)
In other words, can I apply a method to its object as an argument like I would apply a normal function to its argument?
Short answer: no.
Longer answer: you can of course create let-bound functions in a module that call a method on a given type... For example in the code
let l = [1;2;3]
let h1 = l.Head
let h2 = List.hd l
there is a sense in which "List.hd" is the version of what you want for ".Head on a list". Or locally, you can always do e.g.
let AnotherWay = (fun (l:list<_>) -> l.Head)
let h3 = AnotherWay l
But there is nothing general, since there is no good way to 'name' an arbitrary instance method on a given type; 'AnotherWay' shows a way to "make a function out of the 'Head' property on a 'list<_>' object", but you need such boilerplate for every instance method you want to treat as a first-class function value.
I have suggested creating a language construct to generalize this:
With regards to language design
suggestions, what if
SomeType..Foo optArgs // note *two* dots
meant
fun (x : SomeType) -> x.Foo optArgs
?
In which case you could write
list<_>..Head
as a way to 'functionize' this instance property, but if we ever do anything in that arena in F#, it would be post-VS2010.
If I understand your question correctly, the answer is: no you can't. Dot (.) is not an operator in F#, it is built into the language, so can't be used as function.

Resources