I'm having trouble trying to compare an element to all elements of a set. I want to write a boolean function that returns true if an element is not a neighbour and false if an element is a neighbour. We want to colour the chart
so that two countries that share a border are not given the same colour. I will explain it with code
type Country = string;;
type Chart = Set<Country*Country>;;
type Colour = Set<Country>;;
type Colouring = Set<Colour>;;
(* This is how you tell that two countries are neighbours. It requires a chart.*)
let areNeighbours ct1 ct2 chart =
Set.contains (ct1,ct2) chart || Set.contains (ct2,ct1) chart;;
(* val areNeighbours :
ct1:'a -> ct2:'a -> chart:Set<'a * 'a> -> bool when 'a : comparison
*)
I'm having trouble with the canBeExtBy function. If this is my chart and my col:
val myWorld : Chart =
set
[("Andorra", "Benin"); ("Andorra", "Canada"); ("Andorra", "Denmark");
("Benin", "Canada"); ("Benin", "Denmark"); ("Canada", "Denmark");
("Estonia", "Canada"); ("Estonia", "Denmark"); ("Estonia", "Finland");
...]
col = set
["Canada"]
then my function should return false if I call
canBeExtBy col "Denmark" myWorld;;
Here is my code, I get an error which is listed at the bottom.
(* The colour col can be extended by the country ct when they are no neighbours
according to chart.*)
val canBeExtBy :
col:Set<'a> -> ct:'a -> chart:Set<'a * 'a> -> bool when 'a : comparison
*)
Error:
Set.forall(fun x -> areNeighbours x ct) col;;
----------------------^^^^^^^^^^^^^^^^^^
This expression was expected to have type
bool
but here has type
Set<'a * 'a> -> bool
Listen to your types.
This expression was expected to have type
bool
but here has type
Set<'a * 'a> -> bool
Instead of a boolean value, there is a function of type Set<'a * 'b> -> bool. That is a sign for a partially applied function that's missing its last argument of type Set<'a * 'b>. If you look at your areNeighbours function, you can see that it takes three arguments, two of type Country, and one of type Chart, but in canBeExtBy, you're only passing it two Country values, but not the Chart.
To make it compile, canBeExtBy needs to look like this:
let canBeExtBy col ct chart =
Set.forall(fun x -> areNeighbours x ct chart |> not) col
Related
What is the difference between these two functions?
let increment1 x = x +1 // (int -> 'a) -> 'a // why??
let increment2 x = x + 1 // int -> int // this is clear
The lack of space between + and 1 changes the meaning. When there is a space, it reads as operator + applied to argument 1, but without a space it means "positive one", similarly to how -1 means "negative one".
And since +1 is a number of type int, then x +1 must be a function application, applying function x to the argument +1, and therefore x must be of type int -> 'a for some generic type 'a
I was trying to create a random fractional number as follows:
type Fraction=
{
num: int
den: int
}
let makeRandomFraction i =
let n= fun i -> System.Random(i).Next(-50, 51)
let d= fun i -> System.Random(i*3).Next(-50, 51)
{num=n; den=d}
but I am getting an error:
error FS0001: This expression was expected to have type
'int'
but here has type
'int -> int'
Could you please explain the error and the correct way of doing the required.
The error is saying that you're passing a function (of type int -> int) where an int is expected. You can see this more clearly in something like:
let add a b = a + b
let inc x = x + 1
inc add
// ^^^
// This expression was expected to have type 'int' but has type 'int -> int -> int'
The solution here is just to take out the fun i -> parts. That's the (other) syntax for lambdas, but since your i variable is already in scope there's no need to create a function around it.
Out of curiosity, do you have any requirements on what range and distribution of fractions do you want your function to generate? The way the code is currently written - by composing two random numbers in a range -50 .. 50, you will get a distribution with most numbers being close to zero.
Here is a simple histogram built using the XPlot F# library:
open XPlot.GoogleCharts
type Fraction=
{ num: int
den: int }
let makeRandomFraction i =
let n = System.Random(i).Next(-50, 51)
let d = System.Random(i*3).Next(-50, 51)
{num=n; den=d}
[ for i in 0 .. 100000 -> let f = makeRandomFraction i in float f.num / float f.den ]
|> Seq.filter (System.Double.IsInfinity >> not)
|> Seq.countBy (fun f -> int f)
|> Chart.Column
I have a Set<String*String>, and I'm trying to write a function that takes all the elements of that Set and return a Set<String>. My idea is to use Set.fold, and have an empty set accumulator and take the union of the two sets, but I'm running into problems. Here is the code:
type Chart = Set<Country*Country>;;
let countriesInChart (chart : Chart) =
Set.fold(fun (x,y) set -> Set.union [x;y] set ) chart []
But I get this error
Set.fold(fun (x,y) set -> Set.union [x;y] set ) chart [];;
--------------------------------^^^^^^^^^^^^^^^^^^^
error FS0001: This expression was expected to have type
'a * 'b
but here has type
Set<'c>
Look at your types and function signatures.
Set.fold takes a 'State -> 'T -> 'State as the folder function. 'State is the type that you're folding into and that will be the eventual return value, so in this case, you want it to be of type Set<Country>.
That means your lambda can't be right, because the first argument is a tuple. So we should probably switch the arguments of that lambda:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> Set.union [x;y] set ) chart []
Compiling that gives us
(96,39): error FS0001: This expression was expected to have type
Set<'a>
but here has type
'b list
(96,39) in this case is the Set.union function, and of course that is not used correctly, because it requires two sets, but we're passing it one set and a list. We can create a set from the list using Set.ofList:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart []
Again, we're getting a different error, so we're probably making progress:
(96,80): error FS0001: This expression was expected to have type
Set<(Country * Country) * (Country * Country)>
but here has type
'a list
(96,80) is the empty list at the end of the line - and of course, that's wrong, because the third argument to Set.fold needs to be Set<'T>. The set replacement for an empty list would be Set.empty, so let's go with that:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart Set.empty
It compiles! But as you found, it returns Set<Country * Country> instead of just Set<Country>.
Cases like this are when type inference makes it a little harder to see what's going on, so we should go ahead and add type annotations where we know exactly what the types need to be. The most obvious place is the return type of the function:
let countriesInChart (chart : Chart) : Set<Country> =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart Set.empty
Now the error is:
(96,74): error FS0001: Type mismatch. Expecting a
Set<Country>
but given a
Chart
The type 'Country' does not match the type 'Country * Country'
That error is for the second argument of Set.fold, and the reason is that once again, the arguments are in the wrong order. The signature of Set.fold is ('State -> 'T -> 'State) -> 'State -> Set<'T> -> 'State. If we look at what we already have, 'State in this case is Set<Country>, and 'T is Country * Country. That means Set.empty needs to be the second and chart the last argument, and so we arrive at
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) Set.empty chart
The most important rule of functional programming is this: Let the types guide you! ;-)
Try this one:
let f (chart: Chart) =
Set.fold (fun (x:Set<string>) (a,b) -> x |> Set.add a |> Set.add b) Set.empty chart
I'm not sure if the type annotation is necessary but it does force the output to be a Set<string>.
F# allows ".NET" and "OCaml" formatting of signatures. This can be confusing when you fall into the habit of using one style, and then find a situation where you cannot properly format the signature you need. Consider this code, which requires a flexible type as the output of the function input to foo:
let foo n (bar: int -> #seq<'a>) =
(fun () -> Vector.ofSeq (bar n))
let foobar n = Array.ofSeq([1..n])
let x = foo 10 foobar
I could not figure out how to express #seq<'a> in OCaml format. Is it possible?
The following compiles just fine:
type A<'a>(x) =
member __.Get : 'a = x
abstract PairWith : 'b -> ('a * 'b * int)
default __.PairWith y = x, y, 1
type B<'a>(x) =
inherit A<'a>(x)
override __.PairWith y = x, y, 2
let pairAB (x : #A<'a>) y =
x, x.PairWith y
type 'a X (x) =
member __.Get : 'a = x
abstract PairWith : 'b -> ('a * 'b * int)
default __.PairWith y = x, y, 1
type 'a Y (x) =
inherit X<'a>(x)
override __.PairWith y = x, y, 2
let pairXY (x : #('a X)) y =
x, x.PairWith y
So you can guess (and then confirm with F# Interactive) that you are looking for #('a seq).
I'm not exactly sure what you mean, but I assume that you want to put the type variable in front of the type name, e.g. 'a #seq.
According to the language specification (ยง5.1.5) it's not possible since:
A type of the form #type is an anonymous type with a subtype constraint and is equivalent to 'a when 'a :> type, where 'a is a fresh type inference variable.
So you could write your type like: 'a when 'a :> seq<'b>.
EDIT: You could actually use #('a seq), but it looks awkward and I doubt it's what you want.
EDIT2: Didn't see Ramon Snir's answer :).
I'm struggling with the F# type signature notation. For example let's say you have a Fold function:
let rec Fold combine acc l =
...
that may have this type signature:
('a -> 'b -> 'a) -> 'a -> list<'b> -> 'a
which I would read as
a function that has three arguments:
a function that takes an 'a, a 'b and returns an a'
an 'a
a list of 'b
and returns an 'a.
But then it would make more sense for my cavemen brain to express it as
('a, 'b -> 'a), 'a, list<'b> -> 'a
I'm sure there is a semantic reason why parameters are separated with an arrow exactly the same way as the function return type, but somehow I'm missing it and didn't found a clear explanation in books/articles so far. Every time I see a type signature I have to stop quite a bit of time to understand it. I feel like I'm just missing that little piece of the puzzle that makes the "decryption" obvious.
Can someone please enlighten me?
I'm sure there is a semantic reason
why parameters are separated with an
arrow exactly the same way as the
function return type, but somehow I'm
missing it and didn't found a clear
explanation in books/articles so far.
You're reading of the first function is correct. For instant deciphering, type signatures are expressed like this:
val functionName = inputType1 -> inputType2 -> ... -> inputTypeN -> returnType
Generally, arrow notation indicates a function is curry-able.
// val add4 : int -> int -> int -> int -> int
let add4 a b c d = a + b + c + d;;
// val f : (int -> int)
let f = add4 1 2 3 // returns (int -> int) waiting for last argument
Because the function is curried, you can technically write it like this:
// val add4 : int -> int -> int -> int -> int
let add4 = (fun a -> (fun b -> (fun c -> (fun d -> a + b + c + d))));;
// val f : (int -> int)
let f = fun x -> add4 1 2 3 x
If you think about it, the add4 signature is equivalent to this:
val add4 : int -> (int -> (int -> (int -> int) ) )
I believe we use arrow notation because it resembles the structure of the function when we explicitly curry arguments as shown above.
The signatures are written in that way because of what is called Currying. A slightly more accurate way of describing your function is that it takes a (function that takes a 'a and returns a function from a 'b to a 'a) and returns a function that takes a 'a and returns a function from a list<'b> to a 'a. Because of this the type signature can be rewritten as
('a -> 'b -> 'a) -> ('a -> (list<'b> -> 'a))
You could write a similar function in F# which has a type like you're proposing (but in F# it would be written as ('a * 'b -> 'a) * 'a * list<'b> -> 'a. However, the advantage of the existing function is that it's easy to partially apply it by only supplying a prefix of the arguments. For instance:
let sum = List.fold (+) 0
Using your definition, you'd have to write
let sum l = List.fold((fun (x,y) -> x + y), 0, l)
The reason for that is in Functional programming every function actually has only one parameter.
So lets say you have a function called Sum as :
int -> int -> int
It takes 2 int and return one int. Now if you call this function by just passing one int you won't get any compiler error, rather the return value will be of type int -> int. So you see this arrow notation fits with this behavior. This behavior is known as Currying.
Check out : http://en.wikipedia.org/wiki/Currying