In F# there are many different collection-looking syntaxes that compile into something. What are they all, and what do they mean?
let s1 = [a, b, c, d]
let s2 = [a; b; c; d]
let s3 = (a, b, c, d)
let s4 = (a, b, c, d)
let s5 = [|a, b, c, d|]
let s6 = [|a; b; c; d|]
let s7 = a, b, c, d
let s8 = { aa = 3; bb = 4 }
[a, b, c, d] is a list with a single 4-tuple as element.
[a; b; c; d] is a four-element list.
(a, b, c, d) is a 4-tuple.
[|a, b, c, d|] is an array with a single 4-tuple as element.
[|a; b; c; d|] is a four-element array.
a, b, c, d is a 4-tuple.
{ aa = 3; bb = 4 } is a value of a record type with two fields aa and bb.
Answer provided by райтфолд gives you answer, I'll try give you a way to get answer by yourself next time you have a question like this.
The easiest way is to use F# interactive (you can start it from Visual Studio from View -> Other Windows -> F# Interactive). Just type F# code, add double semicolon ;; and hit ENTER. To make your declarations work you have to declare a, b, c and d first. Let's make them all integers:
> let a = 1
let b = 2
let c = 3
let d = 4
;;
val a : int = 1
val b : int = 2
val c : int = 3
val d : int = 4
Now you can try your declarations:
> let s1 = [a, b, c, d];;
val s1 : (int * int * int * int) list = [(1, 2, 3, 4)]
F# Interactive prints back the type of expression that was evaluated. In that case it's (int * int * int * int) list. How to read that? * is used to divide elements of a tuple type, so (int * int * int * int) means a tuple with four elements, all types as int. Following list means a list of those. So (int * int * int * int) list is a list of tuples with four int-typed elements each.
> let s2 = [a; b; c; d];;
val s2 : int list = [1; 2; 3; 4]
Similar concept, this time it's a list of int elements.
> let s3 = (a, b, c, d);;
val s3 : int * int * int * int = (1, 2, 3, 4)
This one was already explained above: int * int * int * int is a four element tuple with all elements typed as int.
> let s5 = [|a, b, c, d|]
let s6 = [|a; b; c; d|];;
val s5 : (int * int * int * int) [] = [|(1, 2, 3, 4)|]
val s6 : int [] = [|1; 2; 3; 4|]
These are very similar to s1 and s2, but instead of list element type is followed by [] - that means it's an array. s5 is an array of (int * int * int * int) elements and s6 is an array of int elements.
> let s7 = a, b, c, d;;
val s7 : int * int * int * int = (1, 2, 3, 4)
Same as s3.
> let s8 = { aa = 3; bb = 4 };;
let s8 = { aa = 3; bb = 4 };;
-----------^^
stdin(18,12): error FS0039: The record label 'aa' is not defined
This one is tricky. To make it work you have to declare record type first:
> type myRecordType = { aa: int; bb: int };;
type myRecordType =
{aa: int;
bb: int;}
with that it works and prints that s8 is an instance of myRecordType:
> let s8 = { aa = 3; bb = 4 };;
val s8 : myRecordType = {aa = 3;
bb = 4;}
let s1 = [a, b, c, d]
Equivalent to [(a, b, c, d)]: a list containing one quadruple (tuple of 4 elements).
let s2 = [a; b; c; d]
A list with 4 elements.
let s3 = (a, b, c, d)
A quadruple.
let s4 = (a, b, c, d)
The same quadruple.
let s5 = [|a, b, c, d|]
Equivalent to [|(a, b, c, d)|]: an array containing one quadruple.
let s6 = [|a; b; c; d|]
An array with 4 elements.
let s7 = a, b, c, d
A quadruple (can omit brackets in this case and when there is no ambiguity).
let s8 = { aa = 3; bb = 4 }
A record definition.
Related
I am new to F#. I am working with a custom type which contains tuples.
type myType =
| obj1 of int * int
| obj2 of string * string
Now I have function which yields the sequence of this myType
type Response = XmlProvider<"""<Result><ns7:value>Item 1</ns7:value>`<ns7:status>1</ns7:status></Result>""", Global=true>`
let comparison (a:Response.Result) (b::Response.Result) = seq {
if a.Status <> b.Status then
yield Status(a.Value, a.Status, b.Status)
}
After that I get the array of myType
let a = """<Result><ns7:value>Item 1</ns7:value>`<ns7:status>1</ns7:status></Result>"""
let b = """<Result><ns7:value>Item 1</ns7:value>`<ns7:status>1</ns7:status></Result>"""
let compareResults = comparison a b |> Seq.toArray
My question is when a traverse through compareResults, how can I get back tuple obj1 and obj2. Currently all I am getting is the object of myType. Is there a way to cast that back into a tuple?
Update
module Script.File1
open System
open FSharp.Data
open HttpClient
type myType =
| Obj1 of string * int * int
| Obj2 of string * string
type Response = XmlProvider<"""<Result><value>Item 1</value><status>1</status></Result>""", Global=true>
let comparison (a:Response.Result) (b:Response.Result) = seq {
if a.Status <> b.Status then
yield Obj1(a.Value, a.Status, b.Status)
}
let a = Response.Parse("""<Result><value>Item 1</value><status>1</status></Result>""")
let b = Response.Parse("""<Result><value>Item 1</value><status>1</status></Result>""")
let compareResults = comparison a b |> Seq.toArray
let run () =
for c in compareResults do
printfn " - %O" c
Assuming you have something like this (to start with a simplified compilable example):
type MyType =
| Obj1 of int * int
| Obj2 of string * string
let demo = seq {
for i in 0 .. 9 do
yield Obj1(i, i) }
Now, demo is a sequence of MyType values that all happen to be Obj1. You can pattern match on the values, but you will need to cover both of the cases, because the compiler does not know that all values in the sequence all Obj1:
for d in demo do
match d with
| Obj1(i1, i2) -> printfn "%d %d" i1 i2
| _ -> failwith "Should not happen"
If you want to avoid this, you could just yield a pair of integers so that the type of demo is seq<int * int>. Then you can iterate over that easily or you can wrap it into Obj1 when needed.
Alternatively, you could change your type definition so that the value is a tuple (wrapped with extra parentheses) rather than just two elements:
type MyType =
| Obj1 of (int * int)
| Obj2 of (string * string)
Now you can more easily pass the int * int value around. For example:
let demo = seq {
for i in 0 .. 9 do
yield i, i }
// Turn sequence of tuples into `MyType`
let objs = Seq.map Obj1 demo
// Iterate over a sequence of tuples
for i1, i2 in demo do
printfn "%d %d" i1 i2
I have this question about matching functions by its signature. I am asking this for learning purposes and I do understand that there are many ways of going around this.
Suppose that in F# I have the following analogous types:
type T1 = int * int * int
type T2 = {a:int ; b:int; c:int}
And the conversion between them is as trivial as
let convert p =
match p with
|(x,y,z) -> {a = x; b = y; c = z}
Suppose also that I have a substantial library of functions that were written for using with T1 that I now want to reuse with T2, such as:
let addT1 a b =
match a, b with
|(x1,y1,z1),(x2,y2,z2) -> (x1 + x2, y1 + y2, z1 + z2)
let negT1 =
function
|(x,y,z) -> (-x,-y-z)
let offset a i =
match a with
|(x,y,z) -> (x + i, y + i, z + i)
As you can see, all functions rely on T1 but may get multiple parameters of T1 or parameters of other types.
I am familiar with this, witch allows me to map any function (f: int * int * int -> 'a) to a function (g: T2 -> 'a):
let funcOfT2 f = fun (t:T2) -> f (t.a, t.b, t.c)
But in the case of addT1, for example, this does not work because of the second parameter:
val addT1 : int * int * int -> int * int * int -> int * int * int
val (funcOfT2 addt1) : (T2 -> int * int * int -> int * int * int)
So, to use a function like funcOfT2 I would have to use it like this, witch is impractical:
let p1 = {a = 1; b = 2; c = 3}
let p2 = {a = 2; b = 3; c = 4}
let x = funcOfT2 (funcOfT2 addT1 p1) p2
val x = int * int * int = (3,5,7)
I could also make a local version of each function of T1 passing the necessary amounts of funcOfT2 or use convert every time I use a Function of T1, but I believe it would be really impractical and make a cluttered code.
Is there anyway of matching the signature of a function so that I can convert any function that takes any T1 to a function of T2?
My idea was something like this, it does not work for many reasons, but I think it may exemplify what I wanted. Is there any way to do it?:
let rec myDream f =
match f with
|(g: T1 -> 'a) -> fun (t:T2) rest -> fOfT2 (g (convert t)) rest
|(g: 'b -> 'c) -> fun x y -> fOfT2 (g x) y
|(g: 'd) -> g d
I want to create a label in F# which uses a mutable variable to return a value. Unfortunately F# sets this label to a constant value. If the value of the mutable changes, the value of the label remains. Isn't it a bit inconsistent? Is there a way to get the label ("a") being dependent of the mutable ("x")?
let mutable x = 0;
let a = x + 2; // I want not to set a to a constant value
let b two = x + two;
x <- 1;
let c = b 2;
let isConsistent = a = c;
val mutable x : int = 1
val a : int = 2
val b : two:int -> int
val c : int = 3
val isConsistent : bool = false
From your own comment you want a to be a function returning x + 2
Direct translation of that is :
let mutable x = 0
let a () = x + 2
let b two = x + two
x <- 1
let c = b 2
let isConsistent = a () = c // don't forget to call the function 'a'
(*
val mutable x : int = 1
val a : unit -> int
val b : two:int -> int
val c : int = 3
val isConsistent : bool = true
*)
in the following code, does array of array A = B?
let A = Array.init 3 (fun _ -> Array.init 2 (fun _ -> 0))
let defaultCreate n defaultValue = Array.init n (fun _ -> defaultValue)
let B = defaultCreate 3 (defaultCreate 2 0)
if I assign values to A and B, they are different ,what happened? thanks.
for i = 0 to 2 do
for j = 0 to 1 do
A.[i].[j] <-i + j
B.[i].[j] <-i + j
printfn "%A vs %A" A B
A = [|[|0; 1|]; [|1; 2|]; [|2; 3|]|] and B = [|[|2; 3|]; [|2; 3|]; [|2; 3|]|]
let B = defaultCreate 3 (defaultCreate 2 0)
You create an array and then you use this array as values for each cell.
It's as if you did something like this:
let a = [|1; 2; 3; 4|]
let b = [|a; a; a; a|]
The same array a is used for every cell (think pointer to a is you're used to C). Thus, modifying b.[0].[1] will change every a.[1].
In my sample:
> b.[0].[1] <- 10;;
val it : unit = ()
> b;;
[|[|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]|]
The same thing happens with your code.
They are not the same.
Arrays are reference types, and are stored on the heap. When you create an array with another array as the default value, you are storing references to the same array, over and over again.
Numbers are another thing. They are immutable, and are stored by value, on the stack. So you can't change the value of 1 to anything other than 1.
To create an "jagged" array, you need to call Array.init from inside the initializer to the first Array.init call, to create new arrays for each slot.
Also; You could use Array.create if you do want to have the same value in every slot. Be careful about reference types though.
let A = Array.init 3 (fun _ -> Array.create 2 0)
In C# the classic swap function is:
void swap (ref int a, ref int b){
int temp = a;
a = b;
b = temp;
}
int a = 5;
int b = 10;
swap( ref a, ref b);
How would I write that with F#?
(Note, I do not want the functional equivalent. I actually need pass by reference semantics.)
Example to Jared's code:
let mutable (a, b) = (1, 2)
let swap (left : 'a byref) (right : 'a byref) =
let temp = left
left <- right
right <- temp
printfn "a: %i - b: %i" a b
swap (&a) (&b)
printfn "a: %i - b: %i" a b
Normally, you would use ref-cells instead of mutable let's.
Try the following
let swap (left : 'a byref) (right : 'a byref) =
let temp = left
left <- right
right <- temp
/// A function that swaps the order of two values in a tuple
let Swap (a, b) = (b, a)