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)
Related
On page 209 - 210 there is an extended example (see below) (I'm using F# 4.5).
In summary what I don't understand is: if I type each statement individually, there is a declaration that raises an error. If I submit the whole script at once, with the functions that come after the declaratation that raises the error, everything is OK. So what happens in interactive when I submit all the statements as a batch? Does the function that follows the error get used to create a specific version of the potential generic? The ionide hints do not show a generic for the whole script.
In detail (sorry it's so long)
If you execute each of the statements in order upto and including the declaration of formatP , (or paste all of them upto and including formatP at once - e.g. select and alt-enter with ionide in vs code) in interactive, it produces an error:
binary.fsx(67,5): error FS0030: Value restriction. The value 'formatP' has been inferred to have generic type
val formatP : ((int * bool) list -> '_a -> unit) when '_a :> OutState
Either make the arguments to 'formatP' explicit or, if you do not intend for it to be generic, add a type annotation.
if you paste all of the script including the functions which follow formatP
let writeData file data =
use outStream = BinaryWriter(File.OpenWrite(file))
formatP data outStream
let readData file =
use inStream = BinaryReader(File.OpenRead(file))
formatU inStream
it works without error.
Given that compilation order is important - what is happening here?
i.e. why do the functions that are declared after formatP allow the function to compile.
Whole script - which functions without error (It's a bit long - but because I really don't understand the issue, I'm not sure what I can remove to create an accurate example illustrating what is happening.
I guess I could drop formatU and readData? (which have the same relationship) but they are needed to make the last 2 stamenets work which sahows that the code does complie and execute as expected):
open System.IO
type OutState = BinaryWriter
type InState = BinaryReader
type Pickler<'T> = 'T -> OutState -> unit
type Unpickler<'T> = InState -> 'T
// P is the suffix for pickling and U is the suffix for unpickling
let byteP (b : byte) (st : OutState) = st.Write(b)
let byteU (st : InState) = st.ReadByte()
let boolP b st = byteP (if b then 1uy else 0uy) st
let boolU st = let b = byteU st in (b = 1uy)
let int32P i st =
byteP (byte (i &&& 0xFF)) st
byteP (byte ((i >>> 8) &&& 0xFF)) st
byteP (byte ((i >>> 16) &&& 0xFF)) st
byteP (byte ((i >>> 24) &&& 0xFF)) st
let int32U st =
let b0 = int (byteU st)
let b1 = int (byteU st)
let b2 = int (byteU st)
let b3 = int (byteU st)
b0 ||| (b1 <<< 8) ||| (b2 <<< 16) ||| (b3 <<< 24)
let tup2P p1 p2 (a, b) (st : OutState) =
(p1 a st : unit)
(p2 b st : unit)
let tup3P p1 p2 p3 (a, b, c) (st : OutState) =
(p1 a st : unit)
(p2 b st : unit)
(p3 c st : unit)
let tup2U p1 p2 (st : InState) =
let a = p1 st
let b = p2 st
(a, b)
let tup3U p1 p2 p3 (st : InState) =
let a = p1 st
let b = p2 st
let c = p3 st
(a, b, c)
/// Outputs a list into the given output stream by pickling each element via f.
/// A zero indicates the end of a list, a 1 indicates another element of a list.
let rec listP f lst st =
match lst with
| [] -> byteP 0uy st
| h :: t -> byteP 1uy st; f h st; listP f t st
// Reads a list from a given input stream by unpickling each element via f.
let listU f st =
let rec loop acc =
let tag = byteU st
match tag with
| 0uy -> List.rev acc
| 1uy -> let a = f st in loop (a :: acc)
| n -> failwithf "listU: found number %d" n
loop []
type format = list<int32 * bool>
//the types in these two lines only get fully inferred if the lines after are part of the batch
//eh?
let formatP = listP (tup2P int32P boolP)
let formatU = listU (tup2U int32U boolU)
//IE if you only run to here it is an error
let writeData file data =
use outStream = BinaryWriter(File.OpenWrite(file))
formatP data outStream
let readData file =
use inStream = BinaryReader(File.OpenRead(file))
formatU inStream
//If you run to here it does not error
writeData "out.bin" [(102, true); (108, false)] ;;
readData "out.bin"
There are two things going on here, only one of which I can fully explain.
The first is the F# value restriction. In this case, the compiler infers that listP is a generic function, which also makes the value formatP generic. But F# doesn't allow a generic value in this situation, so a compiler error occurs. However, when writeData is present, formatP is no longer generic, so the compiler error disappears. You can see a very similar situation explained in detail here.
But why does the compiler think listP is generic in the first place? I'm not sure about this. It infers that st must be compatible with OutState, which is correct from an object-oriented point of view. But it expresses this as a generic constraint, using st : #OutState instead of just st : OutState. (F# calls this a "flexible type".) This generic constraint then cascades to formatP, causing the problem you reported. Someone with more knowledge of the F# compiler might be able to explain this.
Here's a very small example that exhibits the same behavior:
type Example() = class end
let alpha (_ : Example) =
()
let beta f x =
alpha (f x)
let gamma = beta id
// let delta = gamma (Example())
The compiler infers a generic type for beta, which makes gamma illegal when delta is commented out.
To make matters stranger, the same problem occurs even if I explicitly annotate beta so it's not generic:
let beta (f : Example -> Example) (x : Example) =
alpha (f x)
So the compiler thinks gamma is generic even when beta definitely isn't generic. I don't know why that is.
I get a IEnumerable of object from using a SqlCommandProvider. Those objects match my rows and columns. Lets called it B. In my program I created a type matching those columns too. Lets call this record A. How can I actually transform/cast/construct a record c of type A based on values from B?
type A = {k: int; c: string}
let a:A = { k = 1; c = "c" }
let b = {| k = 1; c = "c" |} // lets say that this one simulate the sql's object
let c:A = b
printfn "%A" a
printfn "%A" b
printfn "%A" c
Try it online!
I got an error of type mismatch:
error FS0001: This expression was expected to have type 'A' but here has type '{|c : string ; k : int|}'
Full sample code with the provider:
type A = {k: int; c: string}
let toA c =
(A)c // ???
do
use cmd = new SqlCommandProvider<"
SELECT k, c
FROM Examples
" , connectionString>(connectionString)
cmd.Execute() |> Seq.map toA
sql table if it matters:
k
c
0
a
1
b
I read the doc without finding a solution to my problem. Maybe it is a comprehension problem.
A working solution is to construct a record from the object:
let toA c =
{k = c.k; c = c.c }
cmd.Execute()
|> Seq.map toA
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
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.
I have written a function that takes an array as input and returns an array of equal size as output. For example:
myFunc [| "apple"; "orange"; "banana" |]
> val it : (string * string) [] =
[|("red", "sphere"); ("orange", "sphere"); ("yellow", "oblong")|]
Now I want to assign the results via a let binding. For example:
let [|
( appleColor, appleShape );
( orangeColor, orangeShape );
( bananaColor, bananaShape )
|] =
myFunc [| "apple"; "orange"; "banana" |]
Which works great...
> val orangeShape : string = "sphere"
> val orangeColor : string = "orange"
> val bananaShape : string = "oblong"
> val bananaColor : string = "yellow"
> val appleShape : string = "sphere"
> val appleColor : string = "red"
...except it produces a warning:
warning FS0025: Incomplete pattern matches on this expression. For example, the value '[|_; _; _; _|]' may indicate a case not covered by the pattern(s).
The source and reason for the warning has already been covered, I'm just looking for a succinct work-around. This function call occurs near the top of my function, and I don't like the idea of putting the entire function body inside a match:
let otherFunc =
match myFunc [| "apple"; "orange"; "banana" |] with
| [|
( appleColor, appleShape );
( orangeColor, orangeShape );
( bananaColor, bananaShape )
|] ->
// ... the rest of my function logic
| _ -> failwith "Something impossible just happened!"
That just smells bad. I don't like the idea of ignoring the warning either - goes against my better judgment. Are there any other options open to me, or do I just need to find a different approach entirely?
One possibility if you expect this kind of calling pattern to be frequent is to make wrappers that act on the sizes of tuples you expect, e.g.
myFunc3 (in1,in2,in3) =
match myFunc [|in1;in2;in3|] with
[|out1;out2;out3|] -> out1, out2, out3
_ -> failwith "Internal error"
etc. But all it does is move the ugly code to a standard place, and writing out the wrappers will be inconvenient.
I don't think there's any better option with this API, because there's no way to tell the compiler that myFunc always returns the same number of elements it is passed.
Another option might be to replace myFunc with an IDisposable class:
type MyClass() =
let expensiveResource = ...
member this.MyFunc(v) = ...calculate something with v using expensiveResource
interface IDisposable with
override this.Dispose() = // cleanup resource
and then use it in a block like
use myClass = new MyClass()
let appleColor, appleShape = myClass.MyFunc(apple)
...
Adapting #Ganesh's answer, here's a primitive way to approach the problem:
let Tuple2Map f (u, v)
= (f u, f v)
let Tuple3Map f (u, v, w)
= (f u, f v, f w)
let Tuple4Map f (u, v, w, x)
= (f u, f v, f w, f x)
Example:
let Square x = x * x
let (a,b) = Tuple2Map Square (4,6)
// Output:
// val b : int = 36
// val a : int = 16
But I guess something even more primitive would be this:
let Square x = x * x
let (a,b) = (Square 4, Square 6)
And if the function name is too long, e.g.
// Really wordy way to assign to (a,b)
let FunctionWithLotsOfInput w x y z = w * x * y * z
let (a,b) =
(FunctionWithLotsOfInput input1 input2 input3 input4A,
FunctionWithLotsOfInput input1 input2 input3 input4B)
We can define temporary function
let FunctionWithLotsOfInput w x y z = w * x * y * z
// Partially applied function, temporary function
let (a,b) =
let f = (FunctionWithLotsOfInput input1 input2 input3)
(f input4A, f input4B)