I want to define sumOfSquares without explicity using parameter, relying instead on functional composition
Here's my code below
let sumOfSquares = Seq.map (fun n -> n * n) >> Seq.sum
However, I got the following error
stdin(80,5): error FS0030: Value restriction. The value 'sumOfSquares'
has been inferred to have generic type
val sumOfSquares : ('_a -> int) when '_a :> seq<int>
Either make the arguments to 'sumOfSquares' explicit or, if you do not intend for
it to be generic, add a type annotation.
One way to resolve it is by using parameters
let sumOfSquares nums = nums |> Seq.map (fun n -> n * n) |> Seq.sum
and this will work. However, I want to see if I can define sum of squares by using composition alone
Update
Here's a nice article describing the issue I've encountered: Value Restriction.
Make a type annotation:
let sumOfSquares : seq<int> -> int =
Seq.map (fun n -> n * n) >> Seq.sum
So lets see what happens when the type inference tries to work here. First you have
Seq.map (fun n -> n * n) >> Seq.sum
Now as Seq allows for anything that implements Seq, we can input int list int[] or many others.
As a result, you get this as the type
val sumOfSquares : ('_a -> int) when '_a :> seq<int>
Now the problem is that sumofSquares is a value (which is a function). Unfortunately, you can't have a generic value in a top level binding. You can though have a generic function, if you make the arguments explicit.
As a result, one alternative to a type annotation is to make the argument explicit like so
let sumOfSquares s= s |> Seq.map (fun n -> n * n) |> Seq.sum
And this works
Searching SO for "value restriction errors" should give some more examples of this problem.
Related
I came across this syntax:
[10.; 11.; 12.]
|> List.map (fun a b -> a * b)
in what case does List.map have two parameters (fun a b)?
This is the output in Jupyter Lab:
That's a fun example, because it looks confusing and usually doesn't come up in practice, so it caught me off-guard initially.
In short, what happens is you're mapping a list of floats into a list of float -> float functions. It's easier to see if you rewrite it as something like this:
let results =
[10.; 11.; 12.]
|> List.map (fun a -> (fun b -> a * b))
You pass a float -> float -> float function as the mapper, and it gets partially applied to the element from the input list. The second argument b is not being applied though, so the output of the mapping is a function that takes a float and multiplies it by the partially applied element of the list, and the overall result is a list of float -> float functions.
You can then apply those functions to some value like this:
results
|> List.map (fun f -> f 2.)
I have just been doing a CodeWars exercise - "create a function that takes a list of non-negative integers and strings and returns a new list with the strings filtered out".
My solution used List.filter and it failed for one of the edge cases. So I looked at their solution and it used List.choose - which seemed to pretty much identical to my version except it converted the result to an option before deciding whether to include it in the new list.
I am confused - please can someone explain when it is best to use 'choose' and when it is best to use 'filter'?
I think you have already observed the essence of the answer: filter allows you to test for a condition, but with choose you can also project your value in the same expression, which would take a separate map if using filter.
Since the problem statement isn't clear (a list cannot contain integer and strings at the same time, except when they are boxed; i.e. the type of the list would be obj list), we can look at both scenarios. Note the additional map functions when using filter.
// List of strings that may contain integer representations
["1"; "abc"; "2"; "def"]
|> List.choose (System.Int32.TryParse >> function
| true, i -> Some i
| _ -> None )
["1"; "abc"; "2"; "def"]
|> List.map System.Int32.TryParse
|> List.filter fst
|> List.map snd
Both expressions return int list = [1; 2].
// List of object that are either of type int or of type string
[box 1; box "abc"; box 2; box "def"]
|> List.choose (function
| :? int as i -> Some i
| _ -> None )
[box 1; box "abc"; box 2; box "def"]
|> List.filter (fun i -> i :? int)
|> List.map unbox<int>
In the case of obj list as input the projection serves to provide the correct result type. That might be done in a different way, e.g. with an annotated let binding.
In the end, the decision between the two is down to your personal preferences.
List.choose is strictly more general than List.filter. You can implement List.filter using only List.choose, but not the other way around. You should use List.choose in place of List.filter only when you can't use the latter because it's simpler and describes your intention more accurately.
You can observe this difference pretty much from the type signatures alone.
List.choose : ('T -> 'U option) -> 'T list -> 'U list
List.filter : ('T -> bool) -> 'T list -> 'T list
List.filter can be implemented with List.choose like this:
let filter : ('T -> bool) -> 'T list -> 'T list =
fun predicate ->
List.choose (fun x -> if predicate x then Some x else None)
List.choose can however be implemented (inefficiently) using List.filter along with List.map and Option.get' (it is in fact calledfilterMap` in many languages and libraries):
let choose : ('T -> 'U option) -> 'T list -> 'U list =
fun f list ->
list
|> List.map f
|> List.filter (fun x -> x <> None)
|> List.map Option.get
Note that Option.get can raise an exception, but won't here because we've filtered out the Nones that would cause that. But because it is unsafe, it's easy to make a mistake and because this implementation is not very efficient, it's nice to have List.choose come out-of-the-box.
I have asked a related question here. I want to do a similar thing but this time thread an accumulator though the array of functions. I immediately thought of Array.Reduce or Array.Fold but they are not working for me:
let AddTen x =
x + 10
let MultiplyFive x =
x * 5
let SubtractTwo x =
x - 2
let functionArray = [| AddTen; MultiplyFive; SubtractTwo |]
let calculateAnswer functionArray x = functionArray |>Array.reduce(fun acc f -> f acc)
The last line throws this exception:
Type mismatch. Expecting a
'a -> 'b but given a
'b The resulting type would be infinite when unifying ''a' and ''b -> 'a'
Am I thinking about the problem incorrectly?
Take a look at these two:
let calculateReduce = functionArray |> Array.reduce (fun f g -> f >> g)
let calculateFold x = functionArray |> Array.fold (fun acc f -> f acc) x
In the reduce version, you take an array of functions and compose them into a single function which you can later call on x.
In the fold version you fold over the array of functions, threading the accumulator through and applying each function to it in sequence. x is the initial value of the accumulator here.
Your original code didn't work, because a reduce expects a 'a -> 'a -> 'a function, which in case of an array of functions would imply composition, while you were trying to apply one function of type int -> int to another.
These are the function definitions.
func1: 'a -> unit
func2: 'b -> 'a
func3: string -> 'b list
The current function
let f = Seq.iter((fun a -> func1(func2 a)) func3(s)
This is as far as I got
let f = func3(s)
|> ((fun a -> func2 a
|> func1)
|> Seq.iter)
I have the feeling it should be possible to loose the lambda and the parens'.
You can do without pipes, simply
Seq.iter (func1 << func2) << func3
(this is a function with some arguments [same than func3] and same output than Seq.iter).
You can test it
let func1 x = printfn "Number: %d" x
let func2 (a, b) = a + b
let func3 = Seq.map (fun n -> (n, 2 * n))
let f : (seq<_> -> unit) = Seq.iter (func1 << func2) << func3
f [1..5]
with output
Number: 3
Number: 6
Number: 9
Number: 12
Number: 15
val func1 : x:int -> unit
val func2 : a:int * b:int -> int
val func3 : (seq<int> -> seq<int * int>)
val f : (seq<int> -> unit)
val it : unit = ()
:)
You can use function composition operator >>:
func3() |> Seq.iter (func2 >> func1)
I think the question is, why do you want to use the pipeline operator?
I find your original code quite readable. You should not try to use pipeline operator (or function composition) just for the sake of using them. Now, in your code, the input s comes at the end, which is a bit unfortunate (you cannot quite see what is the main input for the code). I would probably rewrite it as (also, s is not really a descriptive name):
s |> func3
|> Seq.iter (fun a -> func1 (func2 a))
You can use function composition too - but I do not use it very often, because it does not (always) help with readability. But using it in the argument of Seq.iter is probably quite reasonable.
On a completely unrelated note, you could just use for loop and write:
for a in func3 s do
func1 (func2 a)
I actually find this more readable than any other version of the code here (if F# gives you a language feature for iterating over sequences that does exactly what you need, why not use it?)
I am trying to scale a sequence by the first element of the sequence, so the first element will always be one, and then subsequent elements are a ratio of the first element to the nth element of the original sequence.
Here is my code,
open System
open System.Collections
let squish1 (x:Double seq) =
let r = (Seq.head x:Double)
Seq.fold (fun (xi:Double) (r:Double) -> xi/r);;
And I test on this little vector:-
squish1 [|5.0; 1.0; 1.0; 1.0; 1.0; 1.0|];;
I have typed everything because I get this error message
normaliseSequence.fsx(9,1): error FS0030: Value restriction. The value 'it' has been >inferred to have generic type
val it : (Double -> '_a -> Double) when '_a :> seq
Either make the arguments to 'it' explicit or, if you do not intend for it to be generic, >add a type annotation.
But clearly I am misunderstanding because I get the error message even with everything typed. What am I missing?
Any and all advice gratefully received. Thanks
fold expects two more parameters, the seed value and the sequence. This works:
let squish1 (x:Double seq) =
let r = (Seq.head x:Double)
Seq.fold (fun (xi:Double) (r:Double) -> xi/r) 0.0 x
However, I'm guessing you probably want map instead of fold:
let squish1 (x:Double seq) =
let r = (Seq.head x:Double)
Seq.map (fun (xi:Double) -> xi/r) x
Incidentally, I would probably write it this way:
let inline squish1 (x:seq<_>) =
let r = Seq.head x
Seq.map (fun n -> n / r) x
Now it works for all types that support division.