The result is 4. But I do not understand why. Also to where is the 1 fed into? I thought it is being fed into ((-) 2) as the second parameter but its not. Please explain what is happening step by step.
1 |> List.fold (fun x y -> (+) (x y)) ((-) 2) [3;4]
Given is the expression in the question:
1 |> List.fold (fun x y -> (+) (x y)) ((-) 2) [3;4]
To make things a bit simpler, lets throw away the 1 |> part for the moment and focus on the fold.
List.fold a ??? [2;3;4;5] is turned into (a (a (a (a ??? 2) 3) 4) 5. Since we need something to start with, we'd need
to supply something for ???. This is the initial state. So for example List.fold a 1 [2;3;4;5] is turned
into (a (a (a (a 1 2) 3) 4) 5. Note that this doesn't have anything to do with the 1 we threw away earlier.
So to translate this to List.fold (fun x y -> (+) (x y)) ((-) 2) [3;4] its easier to replace the folder (first parameter)
as with something named. The same goes for the second parameter, the initial state. We'd end up with:
let applyAdd x y a = x y + a
let twoMinusN n = 2 - n
List.fold applyAdd twoMinusN [3;4]
If we expand the last expression like we did before, we'd end up with (applyAdd (applyAdd twoMinusN 3) 4).
Reducing it down further (I hope I brace this the right way):
(applyAdd (applyAdd twoMinusN 3) 4)
(applyAdd (applyAdd (fun n -> 2 - n) 3) 4)
(applyAdd ((fun x y a -> x y + a) (fun n -> 2 - n) 3) 4)
(applyAdd (fun a -> (fun n -> 2 - n) 3 + a) 4)
(applyAdd (fun a -> (-1) + a) 4)
((fun x y a -> x y + a) (fun a -> (-1) + a) 4)
(fun a -> (-1) + 4 + a)
(fun a -> 3 + a)
Isn't that strange? Say we started with List.fold (+) 1 [2;3;4;5] we'd end up with:
((+) ((+) ((+) ((+) 1 2) 3) 4) 5
(* or, if that's easier to read: *)
1 + 2 + 3 + 4 + 5
which is 15. All we're left with is a function now, and not a single value. That's where the 1 |> part comes into play:
1 |> (fun a -> 3 + a)
(fun a -> 3 + a) 1
3 + 1
4
Related
For example; the following line
|> Seq.filter(fun i -> i < 123)
is the same thing as
|> Seq.filter((<) 123)
Is there such a thing for the modulo operator? I'm not sure what the 2nd variant is, and can't find it referenced in the documentation either, so it makes searching somewhat difficult. So for bonus points, please tell me what this operator is called! :)
Currently using:
|> Seq.filter (fun i -> i % 2 = 0)
Looking for something like:
|> Seq.filter ((%) 2 = 0)
Your first example is incorrect in saying that fun i -> i < 123 is equal to ((<) 123). That is actually equivalent to fun i -> 123 < i. Let me explain, every operator is just a function but infix rather than prefix. As an example
let (+) x y = x + y
let add x y = x + y
let (-) a b = a - b // notice that the first argument (a) is on the left side of the operator
let subs a b = a - b
knowing this, we can then reason about % and < the same way
let (%) x y = x % y
let (<) x y = x < y
// therefore
fun i -> i < 123
// is equivalent to
fun i -> (<) i 123
// and mathematically equiv to
((>=) 123)
// same with %
fun i -> i % 2
// is equiv to
fun i -> (%) i 2
// thus cant be reduced to eliminate the lambda
Another alternative, if you're dead-set on not writing out the lambda, is to lift it into a function:
let inline isEven x = x % 2 = 0
...
|> Seq.filter isEven
Alas, you are out of luck, because for partial application to be suitable, you need to swap both arguments of the mod operator. The lambda function is way more concise when taking into account that you are applying two operators, which requires function composition.
let flip f a b = f b a
{0..9}
|> Seq.filter ((flip (%) 2) >> ((=) 0))
|> (Seq.map string >> String.concat ", ")
// val it : string = "0, 2, 4, 6, 8"
Given a simple function, where we do pattern matching on the result of a recursive call, such as:
let rec sumProd = function
| [] -> (0,1)
| x::rest -> let (rSum,rProd) = sumProd rest
(x + rSum,x * rProd)
sumProd [2;5] //Expected (7, 10)
How would I go about changing it into something using higher order functions, e.g. foldBack?
let sumProdHigherOrder lst =
List.foldBack (fun x acc -> (acc + x, acc * x)) lst (0,0)
The above seemed almost like the way to do it, but calling it gives the error: The type 'int' does not match the type 'int * int'
sumProdHigherOrder [2;5] //Expected (7, 10)
What am I missing?
Your missing the tuple functions fst and snd:
List.foldBack (fun x acc -> (fst acc + x, snd acc * x)) [2;5] (0,1)
// val it : int * int = (7, 10)
Or even better, decomposing the tuple at the lambda. I see you just found it:
List.foldBack (fun x (s, m) -> (s + x, m * x)) [2;5] (0,1)
Also note that since the operations are commutative you can do a straight fold:
List.fold (fun (s, m) x -> (s + x, m * x)) (0,1) [2;5]
It will be more efficient.
Right! Of course it shouldn't be the same accumulator that gets passed through the list. After staring intensely at the code for some minutes, I figured it out:
let sumProdHigherOrder lst =
List.foldBack (fun x (acc,acc') -> (acc + x, acc' * x)) lst (0,1)
have a code:
//e = 1/2*Sum((yi -di)^2)
let error y d =
let map =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
let sum =
Array.sum map
(sum / 2.0)
let error2 y d =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
|> Array.sum
|> (/) 2.0
as i understood those functions should produce the same results, but there are a big difference in the results. Can anyone explain this?
p.s. Simplified example:
let test = [|1..10|]
let res = test
|> Array.sum
|> (/) 5
i expect test = 11 (sum(1..10) = 55 and then 55 / 5) but after Array.sum pipeline is not working as i want(as result test = 0).
another alternative is to use the reverse pipe operator (<|) so that partial application of (/) is done with arguments in correct order:
let error2 y d =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
|> Array.sum
|> (/) <| 2.0
Edit: see if this helps clarify
x/y = (/) x y = y |> (/) x = x |> (/) <| y
All those are equivalent. The pipe operators are defined as:
(|>) x f = f x
(<|) f x = f x
where f is a function and x is some value. The reverse pipe doesn't look like it does much but it can help clean up some code in certain situations.
You seem to misunderstand order of arguments in infix functions.
You can expand the point-free form as follows:
x |> (/) 5
<=> (/) 5 x
<=> 5 / x
So it's is the reverse of what you expect. It only works fine for commutative functions like (+), (*), etc. If you're keen on point-free style, the flip function is helpful to be used with |>:
let inline flip f x y = f y x
let error2 y d =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
|> Array.sum
|> flip (/) 2.0
The / operator does not work the way you have assumed. You just need to be a bit more explicit and change the last line in error2 to
fun t -> t/2.0
and then it should all work.
The answers being out by a factor of 4 was the giveaway here.
EDIT: To understand what happens with / here consider what happens when you expand out |>
The following are all equivalent
a |> (/) b
((/) b) a //by removing |>
a / b //what happens when / is reinterpreted as a function
My code (below) falls over with a stack overflow exception. Im assuming F# isnt like haskell and dosent play well with recursive lists. Whats the correct way of dealing with recursive lists like this in F# ? Should i pass it an int so it has a determined size?
let rec collatz num =
match num with
|x when x % 2 = 0 ->num :: collatz (x/2)
|x -> num :: collatz ((x * 3) + 1)
let smallList = collatz(4) |> Seq.take(4)
For an infinite list like this, you want to return a sequence. Sequences are lazy; lists are not.
let rec collatz num =
seq {
yield num
match num with
| x when x % 2 = 0 -> yield! collatz (x/2)
| x -> yield! collatz ((x * 3) + 1)
}
let smallList =
collatz 4
|> Seq.take 4
|> Seq.toList //[4; 2; 1; 4]
let collatz num =
let next x = if x % 2 = 0 then x / 2 else x * 3 + 1
(num, next num)
|>Seq.unfold (fun (n, x) -> Some (n, (x, next x)))
I'm a bit stuck on the last step of getting the solution to problem 2 on Project Euler. This is the source I've gotten so far.
#light
module pe2 (* Project Euler Problem 2 solution *)
open System
let Phi = 1.6180339887;;
let invPhi = 1.0/Phi;;
let rootOfFive = 2.236067977;;
let maxFib = 4000000.0;
let Fib n =
System.Math.Round((Phi**n - invPhi**n)/rootOfFive);;
let FibIndices = Seq.unfold(fun i -> Some(i, i+3.0)) 3.0;;
let FibNos = FibIndices |> Seq.map(fun index -> Fib(index));;
let setAllowedFibNos = FibNos |> Seq.filter(fun fn -> (fn <= maxFib));;
// let answer = setAllowedFibNos |> Seq.fold (+) 0.0;
When I uncomment the last line, the process never seems to finish. So I was hoping that someone could give me a gentle nudge in the right direction. I did look at setAllowedFibNos and it looks right but it's also an infinite sequence so I only see the first three terms.
Also, could someone point me to the right way to chain the various sequences together? I tried something like this:
let answer = Seq.unfold(fun i-> Some(i, i + 3.0)) 3.0
|> Seq.map (fun index -> Fib(index))
|> Seq.filter(fun fn -> (fn <= maxFib))
|> Seq.fold (+) 0.0;;
But that didn't work. As you can probably guess I'm just learning F# so please go gentle and if this sort of question has been asked and answered before, please post a link to the answer and I'll withdraw this one.
let rec Fib(n) =
if (n < 2) then
1
else
Fib(n-2) + Fib(n-1)
Seq.initInfinite Fib
|> Seq.takeWhile (fun a -> a <= 4000000)
|> Seq.filter (fun a -> (a % 2) = 0)
|> Seq.fold (+) 0
'setAllowedFibNos' is indeed an infinite seq computation; 'fold' needs the whole sequence, so the 'filter' will run forever looking for another number <= maxFib.
Take a look at takeWhile:
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/FSharp.Core/Microsoft.FSharp.Collections.Seq.html
I think it is what you want instead of filter.
Also note that you can use 'sqrt 5.0'.
I'm still trying to get used to the Seq approach. But, here is my solution without it.
#light
let rec fib n =
match n with
|0|1 -> n
|_ -> fib(n-1) + fib(n-2)
let maxFib = 4000000
let phi = (1.0 + sqrt(5.0)) / 2.0
let upperBound = 1 + int( log10((float(maxFib) - 0.5) * sqrt(5.0)) / log10(phi))
[1..upperBound] |> List.filter (fun x-> x%3=0) |> List.map fib |> List.filter (fun x -> x%2 = 0) |> List.filter (fun x -> x List.sum |> printfn "%d"
My solution is:
Seq.unfold (fun state ->
if (fst state + snd state > 4000000) then None
else Some(fst state + snd state, (snd state, fst state + snd state))) (0,1)
|> Seq.filter (fun x -> x % 2 = 0)
|> Seq.sum;;