What do the let (x = 0) in x * x translate to? A function (fun x -> x * x) 0) ? - This would make sense, as let bindings are expressions - and expressions must return values (just like functions).
Example:
let result1 =
(fun n1 -> (fun n2 ->
(fun n3 -> n1 + n2 + n3 ) 3) 2) 1
let result2 =
let n1 = 1 in
let n2 = 2 in
let n3 = 3 in
n1 + n2 + n3
let result3 =
let n1 = 1
let n2 = 2
let n3 = 3
n1 + n2 + n3
Am I right to assume that result3 is a sugared form of result2, and result2 a sugared form of result1?
Short: Do let in bindings translate to functions?
You can almost see let x = e1 in e2 as a syntactic sugar for (fun x -> e2) e1.
At the basic level, the two expressions mean the same thing - the compiler will probably compile them differently (depending on optimization levels and how it inlines things), but you could often use the second notation instead of the first one.
The one case where they differ is that ML-languages (including F#) only generalize function types written explicitly using the let keyword. This means that if you use fun, the language won't treat it as a generic function. If you want a generic function, you have to use let (and this is not just a compiler artifact, this is actually part of the language).
For example, the following uses let and it works:
let id = (fun x -> x) in ignore(id 1); ignore(id "A")
But the following does not work, because id is not a generic function:
(fun id -> ignore(id 1); ignore(id "A")) (fun x -> x)
The plain old let is just the lightweight syntax form of the verbose let … in.
From MSDN: Verbose Syntax (F#):
nested let bindings:
Lightweight syntax:
let f x =
let a = 1
let b = 2
x + a + b
Verbose syntax:
let f x =
let a = 1 in
let b = 2 in
x + a + b
The let bindings within these function don't translate to functions themselves, however. Both of these translate to identical CIL code:
f:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ldc.i4.2
IL_0005: add
IL_0006: ret
Note that the only function here is the outer function f. The variables a and b are evaluated as constants within the scope of f.
let x = <val> in <expr> is functionally equivalent to (fun x -> <expr>) <val>.
<expr> is an expression
<val> is a value
The in keyword is optional.
Related
I found the following piece of code in the fantomas library for F#. I am having a hard time understanding this as an F# noob. From what I understand, it's a custom operator that takes 3 arguments, but why would an operator need 3 arguments? And what exactly is happening here?
/// Function composition operator
let internal (+>) (ctx: Context -> Context) (f: _ -> Context) x =
let y = ctx x
match y.WriterModel.Mode with
| ShortExpression infos when
infos
|> Seq.exists (fun x -> x.ConfirmedMultiline)
->
y
| _ -> f y
Here's an example of how fantomas uses this operator in ther CodePrinter module.
let short =
genExpr astContext e1
+> sepSpace
+> genInfixOperator "=" operatorExpr
+> sepSpace
+> genExpr astContext e2
Operators behave a lot like function names:
let (++) a b c d =
a + b + c + d
(++) 1 2 3 4
One difference is that operators can be used infix. An operator with more than 2 arguments allows infix only for the first 2 arguments:
// the following is equal:
let f = (++) 1 2 // like a function name
let f = 1 ++ 2 // with infix
f 50 60
I did not find how fantomas uses the operator you mention, would be curious, in particular since fantomas is a high profile f# project.
It might be instructive to compare this to the regular function composition operator, >>. The definition for this is:
let (>>) (f : a' -> b') (g : b' -> c') (x : a') =
g ( f x )
Esentially, it applies f to x, and then applies g to the result.
If we have the following functions:
let plusOne i = i + 1
let timesTwo j = j * 2
And apply it the following way:
let plusOneTimesTwo = plusOne >> timesTwo
What we're really doing is something like this:
let plusOneTimesTwo = (>>) plusOne timesTwo
When you don't supply all of the necessary arguments to a function (in this case, x), what you get is a function that takes the remaining arguments and then returns what the original function would return (this is partial application.) In this case, plusOneTimesTwo's function signature is now x : int -> int.
The example you've listed is essentially the same thing, but it's performing additional logic to determine whether it wants to apply the second function to the result y or to return it as-is.
So my team and I have created a function, wordMarkovChain, which generates a random string with nWords words, whose word-pairs are distributed according to the cooccurrence histogram wCooc.
Now we wanted to create a function which will test the newly created wordMarkovChain, so I can confirm that it's working as it should.
The function, diffw2, which compares two cooccurrence histograms as the average sum of squared differences, needs to take in two parameters, c1 and c2, of type wordCooccurrences and return a double, where c1 and c2 are two cooccurrence histograms of M elements such that c1(i, j) is the number
of times word number i is found following word number j.
The math behind the function should look like this: 1/M^2 * Summation from i=0 to M-1 Summation from i=0 to M-1 (c1(i, j) - c2(i, j))^2.
Sorry, I can't post a picture:(
Our two types which we have created seems to be the problem. c1 and c2 can have a different length but the type wordHistogram inside the type wordCoocurence can also have a different length.
The question is, how can we create such a function?
We tried with for loops, but we think it needs to be a recursive function. We are quite new to the whole concept of programming and are looking for some guidance. Please bear in mind that we do not possess vast knowledge of F#, especially not their in build functions.
CODE
// Types
type wordHistogram = (string * int) list
type wordCooccurrences = (string * wordHistogram) list
let diffw2 (c1 : wordCooccurrences) (c2 : wordCooccurrences) : double =
let mutable res = 0
let z1, z2 = c1 |> List.unzip
let z3, z4 = c2 |> List.unzip
let m1 = c1 |> List.length
let m2 = c2 |> List.length
let m = m1 + m2
for i in 0 .. (m - 1) do
for j in 0 .. (m - 1) do
for k in 0 .. ((z2.[j] |> List.length) - 1) do
res <- res + (snd z2.[j].[k] - snd z4.[j].[k]) * (snd z2.[j].[k] - snd z4.[j].[k])
(1.0 / (float(m * m))) * float(res)
This might get you closer to what you need. This could instead be done using recursive functions, but I usually prefer to use built-in higher-order functions like fold or fold2 when they can do the job. See https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/list.fold2%5B't1%2C't2%2C'state%5D-function-%5Bfsharp%5D
Each call of List.fold2 receives an "accumulator" with an initial value (or "state") of 0.0. This accumulator is passed to the lambda function in the parameter named "acc". As the lambda is applied to each element of the two input lists, it adds the intermediate result to that acc value, which is then returned as the result of the List.fold2 call.
type wordHistogram = (string * int) list
type wordCooccurrences = (string * wordHistogram) list
let diffw2 (c1 : wordCooccurrences) (c2 : wordCooccurrences) =
let m1 = c1 |> List.length
let m2 = c2 |> List.length
let m = m1 + m2
let res =
(0.0, c1, c2) |||>
List.fold2 (fun acc (_str1, hist1) (_str2, hist2) ->
let intermedRes =
(0.0, hist1, hist2) |||>
List.fold2 (fun acc (_str1, freq1) (_str2, freq2) ->
let diff = float (freq1 - freq2)
acc + diff * diff
)
acc + intermedRes
)
(1.0 / float(m * m)) * res
I think you are trying to do the following
let diffw2_ (c1 : wordCooccurrences) (c2 : wordCooccurrences) =
List.zip c1 c2
|> List.sumBy (fun ((_, w1), (_, w2)) ->
List.zip w1 w2
|> List.sumBy (fun ((_,i1), (_,i2)) ->
(float (i1 - i2)) ** 2.0
)
) |> (fun totalSumOfSquares -> totalSumOfSquares / (c1 |> List.length |> float))
This just returns the average square differences between corresponding elements of c1 and c2. It assumes that c1 and c2 have the same structure.
With F# (and functional programming in general), you typically avoid using mutable variables and for loops, in favor of pure functions.
how do you convert an obj list to int type. I am trying to add two lists using a map function below but it doesn't work on obj lists.
let query f=
seq{
let cmd = new OleDbCommand( "SELECT * FROM F" );
let conn = new OleDbConnection( #"Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=D:\Users\df\Documents\Vfolio.accdb;
Persist Security Info=False;" )
conn.Open()
let DAdapt = new OleDbDataAdapter("SELECT * FROM F",conn)
let DTab = new DataSet()
let i= DAdapt.Fill(DTab)
let rowCol = DTab.Tables.[0].Rows
let rowCount = rowCol.Count
for i in 0 .. (rowCount - 1) do
yield f (rowCol.[i])
}
let u= query(fun row -> row.[0])
let a= List.ofSeq u
let v=query(fun row -> row.[1])
let b= List.ofSeq v
let c = List.map2 (fun x y-> x + y) a b
error msg: The type 'obj' does not support the operator '+'
Because row.[i] returns type obj, your u and v become seq<obj>, and thus your a and b become type List<obj>, and therefore x and y are inferred to have type obj, and of course, you can't add two objs, which is exactly what the compiler tells you.
If you are sure that row.[0] and row.[1] are numbers of some kind, you should apply the appropriate cast, for example:
let u= query(fun row -> row.[0] :?> int)
let a= List.ofSeq u
let v=query(fun row -> row.[1] :?> int)
let b= List.ofSeq v
let c = List.map2 (fun x y-> x + y) a b
You can apply this cast in other places, too, depending on your taste and requirements, for example:
let c = List.map2 (fun x y-> (x :?> int) + (y :?> int)) a b
Or:
let a= u |> Seq.cast<int> |> List.ofSeq
let b= v |> Seq.cast<int> |> List.ofSeq
But I like the first example best, because it applies the cast at the earliest known point and results in the least amount of extra code.
But beware: if row.[0] turns out to be not an int at runtime, you will get an InvalidCastException.
P.S. In your List.map2 call, you could specify (+) directly instead of wrapping it in an extra lambda:
List.map2 (+) a b
P.P.S Also, it seems that your List.ofSeq calls are wasteful, for Seq also has a map2:
let u = query(fun row -> row.[0] :?> int)
let v = query(fun row -> row.[1] :?> int)
let c = Seq.map2 (+) u v |> List.ofSeq
P.P.P.S Also, have you noticed that each of the two calls to query generates its own DB connection, command, adapter, and dataset? Did you intend this or did you mean to only have one connection and then fetch different columns from the result? If so, you should only call query once:
let c = query( fun row -> (row.[0] :?> int) + (row.[1] :?> int) ) |> List.ofSeq
I feel silly for even asking this because it seems so trivial but my brain is failing me. If I had the following:
let a, b, c = 1, 1, 1
Is there an eligant way to determine if a, b, and c all hold the same value. Something like:
let result = (a = b = c)
This fails because the expression a = b returns true and the next expression results in true = c and complains that it was expecting int, not bool. The only thing I can think of is:
a = b && a = c && b = c
which won't work when I want to add more variables.
Really what I'm trying to do is this:
let same (x: string * string * string) =
match x with
| (a, a, a) -> true
| _ -> false
I was hoping that I could match all the elements into one element and if they were different it would move on, but it says on the second element in the match that it has already been bound.
To check if every value in a list is the same:
let rec same = function
| x::y::_ when x <> y -> false
| _::xs -> same xs
| [] -> true
Usage
let a, b, c = 1, 1, 1
same [a; b; c] //true
let same (a, b, c) = a = b && b = c
I would try to use the forall function in order to determine if all of the numbers are same.
let list = [a; b; c;];;
List.forall (fun n -> n = a) list;;
val it : bool = true
This solution produces exactly the required syntax. Surprisingly to myself, is fairly fast. Also, is seems to be a good example of using monads, also known as Computation Expressions.
// Generic
let inline mOp1<'a> op sample x = op sample x, sample
let inline mOp2<'a> op1 op2 (b, sample) x = op1 b (op2 sample x), sample
// Implementation for (=) and (&&)
let (==) = mOp1 (=)
let (&=) = mOp2 (&&) (=)
// Use
let ret1 = a == b &= c &= d &= e |> fst
How it works
The approach is a very simplified State monad. The monadic type is a tuple of (bool, 'T). The first component is the boolean value of ongoing calculation, and the second is the sample value to compare with.
(==) would initialize the monad, similar to Delay operator.
(&=) is used for all subsequent comparisons. It is similar to Bind operator.
We don't need Return because fst would serve pretty fine.
mOp1 and mOp2 are abstractions over the logical operations. These allow defining your own operators. Here are examples of or-equal and and-greater-than:
let (|=) = mOp2 (||) (=)
let (.>) = mOp1 (>)
let (&>) = mOp2 (&&) (>)
// Use
let ret2 = a == b |= c |= d |= e |> fst // if any of b,c,d,e equals to a
let ret3 = 5 .> 3 &> 4 |> fst // true: 5>3 && 5>4
let ret4 = 5 .> 3 &> 8 &> 4 |> fst // false
Performance
I really enjoyed the beautiful solution by #ildjarn, but constructing List is quite slow, so my primary goal was performance.
Running a chain of 8 comparisons, 10 million times:
04972ms a=b && a=с && ...
23138ms List-based
12367ms monadic
I currently use this function
let inc (i : int ref) =
let res = !i
i := res + 1
res
to write things like
let str = input.[inc index]
How define increment operator ++, so that I could write
let str = input.[index++]
You cannot define postfix operators in F# - see 4.4 Operators and Precedence. If you agree to making it prefix instead, then you can define, for example,
let (++) x = incr x; !x
and use it as below:
let y = ref 1
(++) y;;
val y : int ref = {contents = 2;}
UPDATE: as fpessoa pointed out ++ cannot be used as a genuine prefix operator, indeed (see here and there for the rules upon characters and character sequences comprising valid F# prefix operators).
Interestingly, the unary + can be overloaded for the purpose:
let (~+) x = incr x; !x
allowing
let y = ref 1
+y;;
val y : int ref = {contents = 2;}
Nevertheless, it makes sense to mention that the idea of iterating an array like below
let v = [| 1..5 |]
let i = ref -1
v |> Seq.iter (fun _ -> printfn "%d" v.[+i])
for the sake of "readability" looks at least strange in comparison with the idiomatic functional manner
[|1..5|] |> Seq.iter (printfn "%d")
which some initiated already had expressed in comments to the original question.
I was trying to write it as a prefix operator as suggested, but you can't define (++) as a proper prefix operator, i.e., run things like ++y without the () as you could for example for (!+):
let (!+) (i : int ref) = incr i; !i
let v = [| 1..5 |]
let i = ref -1
[1..5] |> Seq.iter (fun _ -> printfn "%d" v.[!+i])
Sorry, but I guess the answer is that actually you can't do even that.