Reputation: 339
I am comparing two lists of thangs. Since I'm more familiar with Linq than F#, I did this:
let r1 = (rows1.Zip (rows2, fun r1 r2 -> rowComparer r1 r2)) .All (fun f -> f)
This raises two complaints from the F# linter.
Lint: If `rowComparer` has no mutable arguments partially applied then the lambda can be removed.
Lint: `fun x -> x` might be able to be refactored into `id`.
Of these, I could understand the latter, and tried this:
let r1 = (rows1.Zip (rows2, fun r1 r2 -> rowComparer r1 r2)) .All id
But this made the F# compiler complain:
This expression was expected to have type
'System.Func<bool,bool>'
but here has type
''a -> 'a'
Can someone say how this code can be more righteous?
Upvotes: 1
Views: 232
Reputation: 5751
You can supply the standard function id
as an argument if you create an instance of System.Func
with the correct number of generic type parameters from it. When employing a lambda expression, the F# compiler does that for you.
open System.Linq
let foo rowComparer (rows1 : seq<_>) (rows2 : seq<_>) =
(rows1.Zip (rows2, fun r1 r2 -> rowComparer r1 r2)).All(System.Func<_,_>(id))
// val foo :
// rowComparer:('a -> 'b -> bool) -> rows1:seq<'a> -> rows2:seq<'b> -> bool
Upvotes: 2
Reputation: 6510
I would suggest using the F# List
or Seq
modules instead of LINQ methods. Then you'll be able to use F# types like 'a -> 'a
instead of System.Func<'a, 'a>
, and you can pass id
to the forAll
function. If you could post a complete example, it would be easier to give you a complete answer, but I think something like this would be roughly equivalent to what you're doing with LINQ:
let compare (rowComparer: ('a * 'a) -> bool) rows =
Seq.zip rows >> Seq.map rowComparer >> Seq.forall id
This creates a function that takes two sequences and compares each value in the first to the corresponding value in the second, generating a sequence of booleans. It then returns true if all of the values in the sequence are true, otherwise it returns false. This is achieved using function composition and partial application to build a new function with the required signature.
You can then partially apply a row comparer function to create a specialized compare function for each of your scenarios, as follows:
let compareEqual = compare (fun (a,b) -> a = b)
compareEqual [0; 1; 2] [0; 1; 2] // true
compareEqual [0; 1; 2] [2; 1; 2] // false
Upvotes: 4