I have the following method:
member this.addColumnWithHeading heading column =
this.addColumn (seq { yield heading; yield! (column |> Seq.map string)})
which takes a string heading and any sequence (which is compiled to seq in this case), creates a sequence of strings and calls another method with this data. However, it doesn't work with column being a sequence of floats:
Error 1 The type 'obj' does not match the type 'float' C:\Users\ga1009\Documents\PhD\cpp\pmi\fsharp\pmi\Program.fs 138
How can I define the method addColumnWithHeading so that it works with floats as well?
The built-in string function is an inline function which uses a statically-resolved generic parameter; since your addColumnWithHeading method is not declared inline, the F# type inference has to assume the values in the sequence are of type obj.
There's a simple solution though -- swap out the string function in favor of "manually" calling .ToString() on the values in the sequence. If you do that, F# will be able to use a standard generic parameter type for the sequence so you can pass a sequence of any type you desire.
member this.addColumnWithHeading heading column =
seq {
yield heading
yield! Seq.map (fun x -> x.ToString()) column }
|> this.addColumn
string is inlined so its argument type has to be resolved at compile-time. Since your member is not inlined it picks the most general type it can (obj in this case). Inlining your method will allow column to remain generic.
member inline x.AddColumnWithHeading(heading, column) =
x.AddColumn(seq { yield heading; yield! Seq.map string column })
EDIT
Per the comments to Jack's answer, you might not need to inline your use of string. Certainly, if column will always be seq<float> you should just add a type annotation. Passing seq<string> and moving the string conversion outside the function is another option.
Related
I'm learning F# and struggling trying to use discriminated unions. I have a simple case where I'm trying to use Map.map on a simple discriminated union of the type Map but its saying there is a type mismatch. I'm basically just trying to use the type Prices as a Map
Here is a simplified example:
type Prices = Prices of Map<string, int>
let GetSalePrice (prices: Prices) = prices |> Map.map (fun k v -> (k, v * 2))
Gives me this error:
/Users/luke/code/chronos/Chronos.Mining/Chronos.Mining.Actors/Untitled-1(22,47): error FS0001: Type mismatch. Expecting a
'Prices -> 'a'
but given a
'Map<'b,'c> -> Map<'b,'d>'
The type 'Prices' does not match the type 'Map<'a,'b>'
Given that all I'm doing in the map function is returning the value * 2 I don't understand why I'm getting this error.
You cannot "use Prices as a Map", because Prices is not a Map. The way you have defined it, Prices is a different type, not at all the same as a Map, but it contains an instance of a Map inside it.
If this is indeed what you meant, then in order to get the Map out of a Prices value, you need to pattern-match on it. Like this:
let GetSalePrice (Prices theMap) = theMap |> Map.map ...
Whoa, what's going on here? How is Prices theMap different from prices: Prices? Why are we putting the type name in front of the parameter rather than behind it via a colon? Isn't that how types are denoted in F#?
You may have a bit of a confusion because you're using the same name Prices for both the type and its constructor. To clear this up, let me redefine your type like this:
type PricesType = PricesCtor of Map<string, int>
Now the function would look like:
let GetSalePrice (PricesCtor theMap) = theMap |> Map.map ...
So you see, it's not the type that we're putting in front of the parameter. It's the constructor. And this declaration - (PricesCtor theMap) - tells the compiler that we're expecting a parameter of type PricesType (because that's where PricesCtor belongs), and when we get this parameter, it should be unwrapped, and the map contained within should be named theMap.
This whole process is called "pattern matching". Here, we're matching on the constructor PricesCtor.
Your original function, on the other hand, merely specified the type of the parameter. With my new type definition I might write your original function like this:
let GetSalePrice (prices: PricesType) = prices |> Map.map ...
Here, we specify that our parameter should have type PricesType, but then we're trying to use it as an argument for Map.map, which expects a parameter of type Map<_,_>. No wonder there is a type mismatch!
Pattern matching doesn't have to be in the parameter declaration either. You can pattern-match anywhere in the code. To do that, use the match keyword. This is how your function may be written that way:
let GetSalePrice prices =
match prices with
| PricesCtor theMap -> theMap |> Map.map ...
The match keyword becomes significant as soon as your type has more than one constructor. For example:
type PricesType = PricesAsAMap of Map<string, int> | SinglePrice as int
In this case, if you specify the pattern in the parameter declaration:
let GetSalePrice (PricesAsAMap theMap) = ...
the compiler will warn you that the pattern match is incomplete. Indeed, your function knows what to do when given a SinglePrice value, but what should it do when given a ConstantPrice? You haven't defined that, so the compiler will complain.
This setup is an occasion to use the match keyword:
let GetSalePrice prices =
match prices with
| PricesAsAMap theMap -> theMap |> Map.map ...
| SinglePrice p -> "single item", p
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.
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.
I am running into difficulty with F# in numerous scenarios. I believe I'm not grasping some fundamental concepts. I'm hoping someone can track my reasoning and figure out the (probably many) things I'm missing.
Say I'm using Xunit. What I'd like to do is, provided two lists, apply the Assert.Equal method pairwise. For instance:
Open Xunit
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 Assert.Equal test1 test2
The compiler complains that the function Equal does not take one parameter. As far as I can tell, shouldn't map2 be providing it 2 parameters?
As a sanity check, I use the following code in f# immediate:
let doequal = fun x y -> printf "result: %b\n" (x = y)
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 doequal test1 test2;;
This seems identical. doequal is a lambda taking two generic parameters and returning unit. List.map2 hands each argument pairwise into the lambda and I get exactly what I expected as output:
result: true
result: true
result: false
So what gives? Source shows Xunit.Equal has signature public static void Equal<T>(T expected, T actual). Why won't my parameters map right over the method signature?
EDIT ONE
I thought two variables x and y vs a tuple (x, y) could construct and deconstruct interchangeably. So I tried two options and got different results. It seems the second may be further along than the first.
List.map2 Assert.Equal(test1, test2)
The compiler now complains that 'Successive arguments should be separated spaces or tupled'
List.map2(Assert.Equal(test1, test2))
The compiler now complains that 'A unique overload method could not be determined... A type annotation may be needed'
I think that part of the problem comes from mixing methods (OO style) and functions (FP style).
FP style functions have multiple parameters separated by spaces.
OO style methods have parens and parameters separated by commas.
Methods in other .NET libraries are always called using "tuple" syntax (actually subtly different from tuples though) and a tuple is considered to be one parameter.
The F# compiler tries to handle both approaches, but needs some help occasionally.
One approach is to "wrap" the OO method with an FP function.
// wrap method call with function
let assertEqual x y = Assert.Equal(x,y)
// all FP-style functions
List.map2 assertEqual test1 test2
If you don't create a helper function, you will often need to convert multiple function parameters to one tuple when calling a method "inline" with a lambda:
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2
When you mix methods and functions in one line, you often get the "Successive arguments should be separated" error.
printfn "%s" "hello".ToUpper()
// Error: Successive arguments should be separated
// by spaces or tupled
That's telling you that the compiler is having problems and needs some help!
You can solve this with extra parens around the method call:
printfn "%s" ("hello".ToUpper()) // ok
Or sometimes, with a reverse pipe:
printfn "%s" <| "hello".ToUpper() // ok
The wrapping approach is often worth doing anyway so that you can swap the parameters to make it more suitable for partial application:
// wrap method call with function AND swap params
let contains searchFor (s:string) = s.Contains(searchFor)
// all FP-style functions
["a"; "b"; "c"]
|> List.filter (contains "a")
Note that in the last line I had to use parens to give precedence to contains "a" over List.filter
public static void Equal<T>(T expected, T actual)
doesn't take two parameters - it takes one parameter, which is a tuple with two elements: (T expected, T actual).
Try this instead:
List.map2 Assert.Equal(test1, test2)
It's all there in the type signatures.
The signature for Assert.Equals is something along the lines of 'a * 'a -> unit. List.map2 expects a 'a -> 'b -> 'c.
They just don't fit together.
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2 - works because the lambda wrapping Equals has the expected signature.
List.zip test1 test2 |> List.map Assert.Equal - works because you now have a single list of tuples, and since List.map wants an 'a -> 'b function (where 'a is now a tuple), Assert.Equal is now fair game.
It's simply not true that two values and a tuple are implicitly interchangeable. At least not as far as F# the language is concerned, or the underlying IL representation is concerned. You can think that it's that way when you call into F# code from, say, C# - an 'a -> 'b -> 'c function there is indeed called the same way syntactically as an 'a * 'b -> 'c function - but this is more of an exception than a rule.
According to its signature Xunit.Assert.Equal() takes a single 2 values tuple parameter
As I know, explicit type parameters in value definitions is a one way to overcome "value restriction" problem.
Is there another cases when I need to use them?
Upd: I mean "explicitly generic constructs", where type parameter is enclosed in angle brackets, i.e.
let f<'T> x = x
Polymorphic recursion is another case. That is, if you want to use a different generic instantiation within the function body, then you need to use explicit parameters on the definition:
// perfectly balanced tree
type 'a PerfectTree =
| Single of 'a
| Node of ('a*'a) PerfectTree
// need type parameters here
let rec fold<'a,'b> (f:'a -> 'b) (g:'b->'b->'b) : 'a PerfectTree -> 'b = function
| Single a -> f a
| Node t -> t |> fold (fun (a,b) -> g (f a) (f b)) g
let sum = fold id (+)
let ten = sum (Node(Node(Single((1,2),(3,4)))))
This would likely be rare, but when you want to prevent further generalization (ยง14.6.7):
Explicit type parameter definitions on value and member definitions can affect the process of type inference and generalization. In particular, a declaration that includes explicit generic parameters will not be generalized beyond those generic parameters. For example, consider this function:
let f<'T> (x : 'T) y = x
During type inference, this will result in a function of the following type, where '_b is a type inference variable that is yet to be resolved.
f<'T> : 'T -> '_b -> '_b
To permit generalization at these definitions, either remove the explicit generic parameters (if they can be inferred), or use the required number of parameters, as the following example shows:
let throw<'T,'U> (x:'T) (y:'U) = x
Of course, you could also accomplish this with type annotations.
Most obvious example: write a function to calculate the length of a string.
You have to write:
let f (a:string) = a.Length
and you need the annotation. Without the annotation, the compiler can't determine the type of a. Other similar examples exist - particularly when using libraries designed to be used from C#.
Dealing with updated answer:
The same problem applies - string becomes A<string> which has a method get that returns a string
let f (a:A<string>) = a.get().Length