Not undestanding generics in F# - f#

Let's assume this code:
let ToLower x = (string x).ToLower()
I can call it with:
ToLower 3
or:
ToLower 3.0
but not both since the first caller defines the type.
so, I did this change, with my C# knowledge of generics:
let ToLower (x : 'a) = (string x).ToLower()
but same problem, it looks like the first caller is specializing the generic and that's it.
I'm looking for a solution where the compiler will generate n versions of the assignment, as needed based on the use cases.
What is the proper way to achieve this in F#?

F# type inference uses constraint solving where the use of a function later in the code can affect the type.
This is however only ever a problem when you are using some built-in primitives such as + or string, which are generic, but have special meaning for certain types. For those, you can use inline (in which case, the code gets inlined and the compiler can handle the special meanings in the place where they are used). If you do not use inline, the compiler will fix the type when you first use the function.
If you just define the function and never use it anywhere, then you get a type obj -> string. This is because the compiler used obj as the default type when there were no other constraints.
If you define the function and call it with ToLower 3, the compiler adds a constraint that restricts the argument type to be int (but then you cannot use it with anything else).
The case of string is a bit odd, because you can convert any value to string - but if you want to do this for any value, you have to box it first. Boxing is something that can be done on a generic value, so in this case, you can define this as a generic function:
let ToLower (x:'a) = (string (box x)).ToLower()
ToLower 3.0
ToLower 3
This works because the type of box is 'a -> obj without any other caveats (unlike the type of string which is 'a -> string, but with special handling of certain type parameters).

Related

This expression was expected to have type 'unit' but here has type 'string'

I was attempting to convert this to F# but I can't figure out what I'm doing wrong as the error message (in title) is too broad of an error to search for, so I found no resolutions.
Here is the code:
let getIP : string =
let host = Dns.GetHostEntry(Dns.GetHostName())
for ip in host.AddressList do
if ip.AddressFamily = AddressFamily.InterNetwork then
ip.ToString() // big fat red underline here
"?"
A for loop in F# is for running imperative-style code, where the code inside the for loop does not produce a result but instead runs some kind of side-effect. Therefore, the expression block in an F# for loop is expected to produce the type unit, which is what side-effect functions should return. (E.g., printfn "Something" returns the unit type). Also, there's no way to exit a for loop early in F#; this is by design, and is another reason why a for loop isn't the best approach to do what you're trying to do.
What you're trying to do is go through a list one item at a time, find the first item that matches some condition, and return that item (and, if the item is not found, return some default value). F# has a specialized function for that: Seq.find (or List.find if host.AddressList is an F# list, or Array.find if host.AddressList is an array. Those three functions take different input types but all work the same way conceptually, so from now on I'll focus on Seq.find, which takes any IEnumerable as input so is most likely to be what you need here).
If you look at the Seq.find function's type signature in the F# docs, you'll see that it is:
('T -> bool) -> seq<'T> -> 'T
This means that the function takes two parameters, a 'T -> bool and seq<'T> and returns a 'T. The 'T syntax means "this is a generic type called T": in F#, the apostrophe means that what follows is the name of a generic type. The type 'T -> bool means a function that takes a 'T and returns a Boolean; i.e., a predicate that says "Yes, this matches what I'm looking for" or "No, keep looking". The second argument to Seq.find is a seq<'T>; seq is F#'s shorter name for an IEnumerable, so you can read this as IEnumerable<'T>. And the result is an item of type 'T.
Just from that function signature and name alone, you can guess what this does: it goes through the sequence of items and calls the predicate for each one; the first item for which the predicate returns true will be returned as the result of Seq.find.
But wait! What if the item you're looking for isn't in the sequence at all? Then Seq.find will throw an exception, which may not be the behavior you're looking for. Which is why the Seq.tryFind function exists: its function signature looks just like Seq.find, except for the return value: it returns 'T option rather than 'T. That means that you'll either get a result like Some "ip address" or None. In your case, you intend to return "?" if the item isn't found. So you want to convert a value that's either Some "ip address or None to either "ip address" (without the Some) or "?". That is what the defaultArg function is for: it takes a 'T option, and a 'T representing the default value to return if your value is None, and it returns a plain 'T.
So to sum up:
Seq.tryFind takes a predicate function and a sequence, and returns a 'T option. In your case, this will be a string option
defaultArg takes a 'T option and a default value, and returns a normal 'T (in your case, a string).
With these two pieces, plus a predicate function you can write yourself, we can do what you're looking for.
One more note before I show you the code: you wrote let getIP : string = (code). It seems like you intended for getIP to be a function, but you didn't give it any parameters. Writing let something = (code block) will create a value by running the code block immediately (and just once) and then assigning its result to the name something. Whereas writing let something() = (code block) will create a function. It will not run the code block immediately, but it will instead run the code block every time the function is called. So I think you should have written let getIP() : string = (code).
Okay, so having explained all that, let's put this together to give you a getIP function that actually works:
let getIP() = // No need to declare the return type, since F# can infer it
let isInternet ip = // This is the predicate function
// Note that this function isn't accessible outside of getIP()
ip.AddressFamily = AddressFamily.InterNetwork
let host = Dns.GetHostEntry(Dns.GetHostName())
let maybeIP = Seq.tryFind isInternet host.AddressList
defaultArg maybeIP "?"
I hope that's clear enough; if there's anything you don't understand, let me know and I'll try to explain further.
Edit: The above has one possible flaw: the fact that F# may not be able to infer the type of the ip argument in isInternet without an explicit type declaration. It's clear from the code that it needs to be some class with an .AddressFamily property, but the F# compiler can't know (at this point in the code) which class you intend to pass to this predicate function. That's because the F# compiler is a single-pass compiler, that works its way through the code in a top-down, left-to-right order. To be able to infer the type of the ip parameter, you might need to rearrange the code a little, as follows:
let getIP() = // No need to declare the return type, since F# can infer it
let host = Dns.GetHostEntry(Dns.GetHostName())
let maybeIP = host.AddressList |> Seq.tryFind (fun ip -> ip.AddressFamily = AddressFamily.InterNetwork)
defaultArg maybeIP "?"
This is actually more idiomatic F# anyway. When you have a predicate function being passed to Seq.tryFind or other similar functions, the most common style in F# is to declare that predicate as an anonymous function using the fun keyword; this works just like lambdas in C# (in C# that predicate would be ip => ip.AddressFamily == AddressFamily.InterNetwork). And the other thing that's common is to use the |> operator with things like Seq.tryFind and others that take predicates. The |> operator basically* takes the value that's before the |> operator and passes it as the last parameter of the function that's after the operator. So foo |> Seq.tryFind (fun x -> xyz) is just like writing Seq.tryFind (fun x -> xyz) foo, except that foo is the first thing you read in that line. And since foo is the sequence that you're looking in, and fun x -> xyz is how you're looking, that feels more natural: in English, you'd say "Please look in my closet for a green shirt", so the concept "closet" comes up before "green shirt". And in idiomatic F#, you'd write closet |> Seq.find (fun shirt -> shirt.Color = "green"): again, the concept "closet" comes up before "green shirt".
With this version of the function, F# will encounter host.AddressList before it encounters fun ip -> ..., so it will know that the name ip refers to one item in host.AddressList. And since it knows the type of host.AddressList, it will be able to infer the type of ip.
* There's a lot more going on behind the scenes with the |> operator, involving currying and partial application. But at a beginner level, just think of it as "puts a value at the end of a function's parameter list" and you'll have the right idea.
In F# any if/else/then-statement must evaluate to the same type of value for all branches. Since you've omitted the else-branch of the expression, the compiler will infer it to return a value of type unit, effectively turning your if-expression into this:
if ip.AddressFamily = AddressFamily.InterNetwork then
ip.ToString() // value of type string
else
() // value of type unit
Scott Wlaschin explains this better than me on the excellent F# for fun and profit.
This should fix the current error, but still won't compile. You can solve this either by translating the C#-code more directly (using a mutable variable for the localIP value, and doing localIP <- ip.ToString() in your if-clause, or you could look into a more idiomatic approach using something like Seq.tryFind.

Distinguishing between f# overloaded functions with optional parameters

F# allows overloaded functions to differ only by an optional parameter, for example:
type MyClass() =
member this.func(a: string, b:string) = "func(a,b)"
member this.func(a: string, ?b:string) = "func(a,?b)"
How would you call the first function?
I don't think there is a sensible way to call the first function if the two overloaded functions differ only by an optional parameter. As mentioned in the comments, using this is probably a poor design and you should rename the parameters.
As you probably noticed, when you try calling the function in an ordinary way using MyClass().func("A","B"), you get an error message complaining about the ambiguity:
error FS0041: A unique overload for method 'func' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: member MyClass.func : a:string * ?b:string -> string, member MyClass.func : a:string * b:string -> string
You can call the second overload explicitly in two ways (with or without ?b) thanks to the fact that you can explicitly provide Some value for an optional argument:
MyClass().func("A")
MyClass().func("A",?b=Some "B")
Out of curiosity, it turns out that you can call the first overload via a static member constraint. This is quite ugly and you probably shouldn't be doing this, but it calls the first overload:
let inline callFunc (o:^T) a b =
(^T : (member func : string * string -> string) (o, a, b))
callFunc (MyClass()) "A" "B"

Need commentary on what this Map.ofSeq signature means

Can anyone please breakdown what this method signature means?
/// Returns a new map made from the given bindings.
/// elements: The input sequence of key/value pairs.
val ofSeq : elements:seq<'Key * 'T> -> Map<'Key,'T> when 'Key : comparison
Here is how it's used:
let grid = [ for i in 0..8 -> (i, true) ] |> Map.ofSeq
Specifically, can some one break this method signature into segments and explain the function of each segment?
NOTE:
I am new to F# and really do want to understand the low level details of the language.
val ofSeq : elements : seq<'Key * 'T> -> Map<'Key,'T> when 'Key : comparison
Let's break it down. First of all, the presence of arrows means it's a function.
Each arrow says, simplistically speaking, that when I give it something of the type on the left, I get the thing on the right. Note that F# supports curried arguments, that means I can supply arguments one at a time, in the process returning functions with progressively fewer arguments.
In this case, your function only takes only one argument.
Your argument elements is of type seq<'Key * 'T>. That is a sequence of tuples of two generic types: 'Key' and 'T'.
When I supply this function with something of type seq<'Key * 'T>, it is telling me that it will return a Map<'Key,'T>. That is a Map which has keys of type 'Key and values of type 'T.
Finally you have a type constraint when 'Key : comparison this restricts the generic type 'Key to be something which supports comparison, i.e. a type which implements the IComparable interface. This type constraint is required because the Map is implemented using a binary tree which uses comparsion for its concept of ordering.

Currying functions with format dependent types

As far as I'm aware, F# doesn't handle printfn like it does other functions because of it's type dependence on the string parameter. Could someone explain to me why that prevents me from doing
let printn = printfn "%A"
The error says the type is infered to ('a -> unit) and that I need to add an explicit parameter or a type annotation. Why? I'm perfectly fine with the type it inferred it to. Also, if I add an explicit point, it still has the same type.
Because printn would be a simple value the way you define it. And values can't be generic in the .NET runtime.
Make the parameter explicit so it is a function:
let printn value = printfn "%A" value
For more information, see the topic Value Restriction on MSDN.

Use of `inline` in F#

The inline keyword in F# seems to me to have a somewhat different purpose than what I'm used to in e.g. C. For example, it seems to affect a function's type (what are "statically resolved type parameters"? Aren't all F# types resolved statically?)
When should I be using inline functions?
The inline keyword indicates that a function definition should be inserted inline into any code which uses it. Most of the time, this will not have any effect on the type of the function. However, in rare cases, it can lead to a function which has a more general type, since there are constraints which cannot be expressed in the compiled form of the code in .NET, but which can be enforced when the function is being inlined.
The primary case where this applies is the use of operators.
let add a b = a + b
will have a monomorphic inferred type (probably int -> int -> int, but it could be something like float -> float -> float if you have code which uses this function at that type instead). However, by marking this function inline, the F# compiler will infer a polymorphic type:
let inline add a b = a + b
// add has type ^a -> ^b -> ^c when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
There is no way to encode this type constraint in a first class way in compiled code on .NET. However, the F# compiler can enforce this constraint at the site where it inlines the function, so that all operator uses are resolved at compile time.
The type parameters ^a, ^b, and ^c are "statically resolved type parameters", which means that the types of the arguments must be statically known at the site where those parameters are being used. This is in contrast to normal type parameters (e.g. 'a, 'b, etc.), where the parameters mean something like "some type which will be supplied later, but which can be anything".
You should use inline when you need to define a function that must have its type (re)evaluated at the site of each usage, as opposed to a normal function, which will have its type evaluated (inferred) only at the site of first usage, and then be regarded as being statically typed with that first inferred type signature everywhere else thereafter.
In the inline case, the function definition is effectively generic/ polymorphic, whereas in the normal (none-inline) case, the function is statically (and often implicitly) typed.
So, if you use inline, the following code:
let inline add a b = a + b
[<EntryPoint>]
let main args =
let one = 1
let two = 2
let three = add one two
// here add has been compiled to take 2 ints and return an int
let dog = "dog"
let cat = "cat"
let dogcat = add dog cat
// here add has been compiled to take 2 strings and return a string
printfn "%i" three
printfn "%s" dogcat
0
will compile, build and run to produce the following output:
3
dogcat
In other words, the same add function definition has been used to produce both a function that adds two integers, and a function that concatenates two strings (in fact the underlying operator overloading on + is also achieved under the hood using inline).
Whereas this code, identical except that the add function is no longer declared inline:
let add a b = a + b
[<EntryPoint>]
let main args =
let one = 1
let two = 2
let three = add one two
// here add has been compiled to take 2 ints and return an int
let dog = "dog"
let cat = "cat"
let dogcat = add dog cat
// since add was not declared inline, it cannot be recompiled
// and so we now have a type mismatch here
printfn "%i" three
printfn "%s" dogcat
0
will NOT compile, failing with this complaint:
let dogcat = add dog cat
^^^ - This expression was expected to have type int
but instead has type string
A good example of where using inline is appropriate, is when you want to define a high order function (HOF, i.e. a function taking (other) functions as arguments), e.g. a generic function to reverse the order of the application of arguments of a function with 2 arguments, e.g.
let inline flip f x y = f y x
as is done in the answer from #pad to this question Different argument order for getting N-th element of Array, List or Seq.
When should I be using inline functions?
The most valuable application of the inline keyword in practice is inlining higher-order functions to the call site where their function arguments are also inlined in order to produce a singly fully-optimized piece of code.
For example, the inline in the following fold function makes it 5× faster:
let inline fold f a (xs: _ []) =
let mutable a = a
for i=0 to xs.Length-1 do
a <- f a xs.[i]
a
Note that this bears little resemblance to what inline does in most other languages. You can achieve a similar effect using template metaprogramming in C++ but F# can also inline between compiled assemblies because inline is conveyed via .NET metadata.
The F# component design guidelines only mention a little about this. My recommendation (that aligns well with what's said there) is:
Don't use inline
Exception: you might consider using inline when writing mathematical libraries to be consumed by other F# code and you want to write functions that are generic over different numeric data types.
There are lots of other "interesting" uses of inline and static member constraints for "duck-typing" kinds of scenarios that work a bit like C++ templates. My advice is to avoid all of that like the plague.
#kvb's answer goes into more depth about what 'static type constraints' are.

Resources