What does this statement mean and why would I write code like that?
let id x = x in (id 3, id "Three")
F# 3.0 spec: 6.6 Definition Expressions
It defines identity function:
let id x = x
in this expression:
(id 3, id "Three")
so result of this expression is a tuple of type (int * string):
(3, "Three")
Edit:
You don't necessarily need to write code like this (maybe in very rare cases). By default F# uses light syntax without in like this:
let id x = x // Define the function
(id 3, id "Three") // Apply it to the elements of tuple
When you are using verbose syntax you don't have to follow whitespace indentation rules. Here it is described more clearly: http://fsharpforfunandprofit.com/posts/fsharp-syntax/
I believe verbose syntax is used mostly when you need to use let in a one line expression as in your sample
let v = expr in body
defines a new environment with the name v bound to expr and then evaluates body in the created environment. In this case id is defined to be a function of type a -> a which just returns its argument. The body
(id 3, id "Three")
is then evaluated with id bound to the above function.
If id x = x then a) id 3 = 3 and b) id "three" = "three". Put it together, in (id 3, id "three"), if we let id x = x then the result is that (id 3, id "three") = (3, "three"). That's the gist of it.
Related
See I have a single case discriminated union
type R = R of string * int * sting option * .....
And I got a value of R.
let r: R = getAValue ()
Now I need to replace the first item of r to an empty string and keep all other value. How to do it? Record type has the with construct
let r' = { r with Item1 = "" }
I know it can use 'pattern match' to extract all the items and create a new one. But it seems very cumbersome.
I assume you do not want to involve reflection, do you?
Then, I believe your only option would be using pattern matching. The (quite limited) burden would be defining the r-ity of your type Ras a pattern for matching.
Let's assume, for example, that your R wraps a tuple of 3 elements, i.e. has r-ity 3:
type R = R of string * int * string option
In this case all you need is to do define the following function:
let modR = function
| R(x,y,z) -> R("",y,z)
The signature of modR is R -> R, a quick check of your scenario:
let r = R("abc",1,None)
modR r
in fsi brings back
>
val it : R = R ("",1,None)
All you would need for applying the above to your specific R is set the actual r-ity of your type into the pattern.
UPDATE: As Fyodor Soikin pointed, a matching function isn't needed at all for unwrapping a single-case DU (see the docs). The sought convertion function definition may be defined as simple as
let modR (R(_,y,z)) = R("",y,z)
UPDATE2: While considering the comment from ca9163d9 I recalled just another flavor of pattern matching, namely as Pattern. Using it while implementing the sought conversion in the form of DU member gives:
type R = R of string * int * string option with
member self.modR() = let R(_,b,c) as x = self in R("",b,c)
Also #FyodorSoikin and #kaefer have pointed out in the comments that as x form isn't required for the simple DU unwrapping, similarly to terser modR function definition above:
member self.modR() = let (R(_,b,c)) = self in R("",b,c)
In OPL (Optimization Programming Language), we have a data structure name tuple. OPL tuple correspond to Record in F#. Here is how it is defined:
tuple Point {
int x;
int y;
};
Like in F#, we can access field by using dot notation
int x = p.x;
We can group tuples in a Set:
{Point} points = {<1,2>, <2,3>};
A difference is that like in database systems, tuple structures can be associated with keys. Tuple keys enable to access data organized in tuples using a set of unique identifiers. In the following example, the nurse tuple is declared with the key name of type string.
tuple nurse {
key string name;
int seniority;
int qualification;
int payRate;
}
{ nurse } nurses = …;
The nice thing about key, is that we can initialize an array this way
int NumberOfChild [n in nurses] = 0;
and accessing a value by using only the key:
NumberOfChild[<"Isabelle">]=20;
leaving out the fields with no keys. This is equivalent to:
NumberOfChild[<"Isabelle",3,1,16>]=20;
Also, using key means that there will be no two tuples with the same key. Like primary key in database.
Question is: Does some type like this exist in F#? Record with key?
My goal: I would like to define a node structure with many attribute. And load a graph structure by only giving the key of the node and not the entire Record since I would load the graph from a database.
type Node = {
nodeKey : int;
nodeName : string;
nodeAttribute1 : string;
nodeAttribute2 : string }
let Graph = [
(1, 2);
(1, 3);
(2, 4);
(3, 4) ]
Where the int in the graph tuple represent nodeKey.
I would like to do operation using the graph but accessing the node information using the key only.
OPL Grammar
No, there's no such language-level concept. All record fields are created equal, so to speak.
That doesn't preclude you from:
synthesizing a key for a record based on one or more field values,
using such a key as a key in a Map that would hold your records or any additional values.
So you can have something like this:
type Nurse = { name: string; seniority: int; qualification: int; payRate: int }
let nurses = [ { name = "Isabelle"; seniority = 3; qualification = 1; payRate = 16 } ]
let numberOfChildren =
[ "Isabelle", 20 ]
|> Map.ofSeq
let nursesWithNumberOfChildren =
[ for nurse in nurses do
match numberOfChildren |> Map.tryFind nurse.name with
| Some children -> yield nurse, children
| None -> yield nurse, 0 ]
Using similar approach you can separate your graph and node data - store only keys in the graph and maintain a mapping that goes from keys to full node records.
//If I read data from a database, I would receive the data in the following form:
type XYZ = {X:int;
Y:string;
Z:float}
let recordsXYZ = [{X=1;Y="A";Z=1.0};{X=2;Y="b";Z=1.0};{X=3;Y="A";Z=1.0}]
//I can create a map this way
let mapXYZ1=recordsXYZ|>Seq.groupBy (fun a ->a.X)|>Map.ofSeq
//But I don't want a Map<int,seq<XYZ>>
//This is what I want
let mapXYZ2=recordsXYZ|>Seq.map (fun a -> (a.X,{X=a.X;Y=a.Y;Z=a.Z}))|>Map.ofSeq
//Or maybe this is cleaner but this need to define another type
type YZ = {Y:string;
Z:float}
let mapXYZ3=recordsXYZ|>Seq.map (fun a -> (a.X,{Y=a.Y;Z=a.Z}))|>Map.ofSeq
If I understand correctly, your best bet is simply a cleaner alternative to Seq.groupBy for your purposes. Here is the core of it, in one line:
let inline project projection value = projection value, value
Given a simple helper function, not specific to XYZ
let projectToMap projection values = values |> Seq.map (project projection) |> Map.ofSeq
it becomes trivial to cleanly create maps of XYZ from any "key":
let mappedByX = xyzs |> projectToMap (fun { X=x } -> x) // Map<int, XYZ>
let mappedByY = xyzs |> projectToMap (fun { Y=y } -> y) // Map<string, XYZ>
let mappedByZY = xyzs |> projectToMap (fun { Y=y; Z=z } -> z, y) // Map<float*string, XYZ>
Online Demo
I am trying to iterate through an IDictionary (reasons explained later...) in F#, and round each value to a specified precision. Essentially this is what I'm trying to do:
List.iter (fun(x) -> a.Item(x) <- Math.Round(a.Item(x), input.precision)) (ICollectionToDoubleList a.Keys)
(where ICollectionToDoubleList takes the ICollection a.Keys and casts it to a double list).
However since you can't alter mutable variables inside closures, this doesn't compile.
My first attempt at a solution was this:
List.iter (fun(x) -> let p = Math.Round(a.Item(x), input.precision)
a.Item(x) := p
) (ICollectionToDoubleList a.Keys)
However I'm getting the error:
This expression was expected to have type
'a ref
but here has type
double
on a.Item(x)
I could convert the IDictionary into two lists (or a list of tuples), perform the rounding, and re-cast into an IDictionary, but this seems a bit messy and convoluted.
Any guidance greatly appreciated.
EDIT:
I forgot to mention a was defined as:
let mutable (a : IDictionary<double,double>) = ...
I think you want
a.Item(x) <- p
In F# you use <- to assign to mutable values, whilst := assign to ref values.
You could even use
a.[x] <- p
for a slightly simpler version.
Explaination of what mutable means (it behaves like the opposite of const in C)
let mutable m = [|1|]
let t = [|1|]
m.[0] <- 0
t.[0] <- 0 //neither of these change m or t - only elements so they are fine
m <- [|1;2;3;|] //fine as m is mutable
t <- [|1;2;3;|] //not allowed as t is not mutable
If you are used to const in C, the above are roughly equivalent to
int* m = {1};
const int* t = {1}
note, neither is equivalent to
const int* q const = {1}
which is I think what you thought not mutable meant.
Ok so I've discovered the answer...
I have defined a as:
let mutable (a : IDictionary<double,double>) = ...
If I change this to
let (a : IDictionary<double,double>) = ...
then this compiles. It seems a little counter-intuative to me that a non-mutable value can be mutated, but a mutatable variable cannot!!
Is it possible to express something like this:
type id = int > 0
I know its not possible to do statically, since this would mean F# has dependent types. In C# I'm used to do this sort of thing with code contracts and get a runtime enforcement. I'm looking for something similiar here.
Thanks
EDIT:
Thank you for all the answers which have various pros and cons. At the monent I'm only using a small subset of F#, a subset of the ocaml core that lends itself easily to program proofs. So no classes.
Contrary to what others said, I would suggest not using classes here, if I understood your problem correctly.
Since the value is immutable, we need applying constraint only once. Any wrapper classes would be an overhead and load GC. Instead, a simple function will do the job:
let inline constrained predicate errormessage value =
if not (predicate value)
then invalidArg "value" errormessage
else value
let positive =
constrained (fun x -> x > 0) "Value must be positive"
let int1 = positive 5 // OK
let int2 = positive -3 // ArgumentException
You can do the same for other types:
let mustBeLong =
constrained (fun (x:string) -> x.Length > 3) "String must be long"
let str1 = mustBeLong "foobar" // OK
let str2 = mustBeLong "baz" // ArgumentException
Using the same within a struct:
type Point2D =
struct
val X: int
val Y: int
new(x: int, y: int) = { X = positive x; Y = positive y }
end
let point1 = Point2D(5, 3) // OK
let point2 = Point2D(5, -2) // ArgumentException
Define it as a union type:
type Id = Id of int
and shadow the constructor with another function:
let Id n =
assert(n > 0)
Id n
In F#, you have to resort to classes and check arguments inside constructors. Other types such as discriminated unions, records and structs have implicit constructors which you can't easily alter.
type Id(i: int) =
do if i <= 0 then
invalidArg "i" "the argument has to be a positive integer"
member x.Value = i
Pattern matching doesn't play nicely with classes. You can remedy the problem using active patterns:
let (|Id|) (id: Id) = id.Value
let id = Id(1)
match id with
| Id 1 -> printfn "matched"
| _ -> printfn "unmatched"
You could create a generic class like so:
type verify<'t>(t:'t,cond) =
let mutable tval = t
let _verify v = if not (cond v) then failwith "bad argument"
do _verify tval
member x.get() = tval
member x.set v =
_verify v
tval <- v
then you can use it with
verify(1,fun t -> t>0)
using .set will recheck the condition.
I'm reading Expert F# book and I found this code
open System.Collections.Generic
let divideIntoEquivalenceClasses keyf seq =
// The dictionary to hold the equivalence classes
let dict = new Dictionary<'key,ResizeArray<'T>>()
// Build the groupings
seq |> Seq.iter (fun v ->
let key = keyf v
let ok,prev = dict.TryGetValue(key)
if ok then prev.Add(v)
else let prev = new ResizeArray<'T>()
dict.[key] <- prev
prev.Add(v))
dict |> Seq.map (fun group -> group.Key, Seq.readonly group.Value)
and the example use:
> divideIntoEquivalenceClasses (fun n -> n % 3) [ 0 .. 10 ];;
val it : seq<int * seq<int>>
= seq [(0, seq [0; 3; 6; 9]); (1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8])]
first for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang..specially compared to clojure. But the problem is not this...I'm having problems with the Dictionary definition
when I type this:
let dict = new Dictionary<'key,ResizeArray<'T>>();;
I get this:
pruebafs2a.fs(32,5): error FS0030: Value restriction. The value 'dict' has been inferred to have generic type
val dict : Dictionary<'_key,ResizeArray<'_T>> when '_key : equality
Either define 'dict' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
is It ok?...
thanks so much
improve question:
Ok I've been reading about value restriction and I found this helpfull information
In particular, only function definitions and simple immutable data
expressions are automatically generalized
...ok..this explains why
let dict = new Dictionary<'key,ResizeArray<'T>>();;
doesn't work...and show 4 different techniques, although in my opinion they only resolve the error but aren't solutions for use generic code:
Technique 1: Constrain Values to Be Nongeneric
let empties : int list [] = Array.create 100 []
Technique 3: Add Dummy Arguments to Generic Functions When Necessary
let empties () = Array.create 100 []
let intEmpties : int list [] = empties()
Technique 4: Add Explicit Type Arguments When Necessary (similar to tec 3)
let emptyLists = Seq.init 100 (fun _ -> [])
> emptyLists<int>;;
val it : seq<int list> = seq [[]; []; []; []; ...]
----- and the only one than let me use real generic code ------
Technique 2: Ensure Generic Functions Have Explicit Arguments
let mapFirst = List.map fst //doesn't work
let mapFirst inp = List.map fst inp
Ok, in 3 of 4 techniques I need resolve the generic code before can work with this...now...returning to book example...when the compile knows the value for 'key and 'T
let dict = new Dictionary<'key,ResizeArray<'T>>()
in the scope the code is very generic for let key be any type, the same happen with 'T
and the biggest dummy question is :
when I enclose the code in a function (technique 3):
let empties = Array.create 100 [] //doesn't work
let empties () = Array.create 100 []
val empties : unit -> 'a list []
I need define the type before begin use it
let intEmpties : int list [] = empties()
for me (admittedly I'm a little dummy with static type languages) this is not real generic because it can't infer the type when I use it, I need define the type and then pass values (not define its type based in the passed values) exist other way define type without be so explicit..
thanks so much..really appreciate any help
This line
let dict = new Dictionary<'key,ResizeArray<'T>>();;
fails because when you type the ;; the compiler doesn't know what 'key and 'T are. As the error message states you need to add a type annotation, or allow the compiler to infer the type by using it later or make it a function
Examples
Type annotation change
let dict = new Dictionary<int,ResizeArray<int>>();;
Using types later
let dict = new Dictionary<'key,ResizeArray<'T>>()
dict.[1] <- 2
using a function
let dict() = new Dictionary<'key,ResizeArray<'T>>();;
This actually doesn't cause an issue when it's defined all together. That is, select the entire block that you posted and send it to FSI in one go. I get this:
val divideIntoEquivalenceClasses :
('T -> 'key) -> seq<'T> -> seq<'key * seq<'T>> when 'key : equality
However, if you type these individually into FSI then as John Palmer says there is not enough information in that isolated line for the interpreter to determine the type constraints. John's suggestions will work, but the original code is doing it correctly - defining the variable and using it in the same scope so that the types can be inferred.
for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang.
I agree completely – it's slightly tangential to your direct question, but I think a more idiomatic (functional) approach would be:
let divideIntoEquivalenceClasses keyf seq =
(System.Collections.Generic.Dictionary(), seq)
||> Seq.fold (fun dict v ->
let key = keyf v
match dict.TryGetValue key with
| false, _ -> dict.Add (key, ResizeArray(Seq.singleton v))
| _, prev -> prev.Add v
dict)
|> Seq.map (function KeyValue (k, v) -> k, Seq.readonly v)
This allows sufficient type inference to obviate the need for your question in the first place.
The workarounds proposed by the other answers are all good. Just to clarify based on your latest updates, let's consider two blocks of code:
let empties = Array.create 100 []
as opposed to:
let empties = Array.create 100 []
empties.[0] <- [1]
In the second case, the compiler can infer that empties : int list [], because we are inserting an int list into the array in the second line, which constrains the element type.
It sounds like you'd like the compiler to infer a generic value empties : 'a list [] in the first case, but this would be unsound. Consider what would happen if the compiler did that and we then entered the following two lines in another batch:
empties.[0] <- [1] // treat 'a list [] as int list []
List.iter (printfn "%s") empties.[0] // treat 'a list [] as string list []
Each of these lines unifies the generic type parameter 'a with a different concrete type (int and string). Either of these unifications is fine in isolation, but they are incompatible with each other and would result in treating the int value 1 inserted by the first line as a string when the second line is executed, which is clearly a violation of type safety.
Contrast this with an empty list, which really is generic:
let empty = []
Then in this case, the compiler does infer empty : 'a list, because it's safe to treat empty as a list of different types in different locations in your code without ever impacting type safety:
let l1 : int list = empty
let l2 : string list = empty
let l3 = 'a' :: empty
In the case where you make empties the return value of a generic function:
let empties() = Array.create 100 []
it is again safe to infer a generic type, since if we try our problematic scenario from before:
empties().[0] <- [1]
List.iter (printfn "%s") (empties().[0])
we are creating a new array on each line, so the types can be different without breaking the type system.
Hopefully this helps explain the reasons behind the limitation a bit more.