Built in equality of lists using a custom comparison function?
Is there a built-in function which does the following?
let rec listsEqual xl yl f =
match xl, yl with
| [], [] -> true
| [], _ | _, [] -> false开发者_StackOverflow中文版
| xh::xt, yh::yt -> if f xh yh then listsEqual xt yt f else false
Updated, further elaboration: and in general is there any way to tap in to structural comparison but using a custom comparison function?
List.forall2 : (('a -> 'b -> bool) -> 'a list -> 'b list -> bool)
But it takes f before the lists. You can create your function like this:
let listsEqual x y f =
if List.length x = List.length y then
List.forall2 f x y
else
false
Remember that List.forall2
assumes the lengths are the same.
Concerning Seq.compareWith, you wrote:
not quite, two problems 1) expects the two sequences be of the same type, 2) doesn't short circuit
2) is wrong, the function really does a court-circuit. 1) is true. Take Seq.compareWith from F# library, modify (or remove) the type annotation and it will work for sequences of different types.
[<CompiledName("CompareWith")>]
let compareWith (f:'T1 -> 'T2 -> int) (source1 : seq<'T1>) (source2: seq<'T2>) =
//checkNonNull "source1" source1
//checkNonNull "source2" source2
use e1 = source1.GetEnumerator()
use e2 = source2.GetEnumerator()
let rec go () =
let e1ok = e1.MoveNext()
let e2ok = e2.MoveNext()
let c = (if e1ok = e2ok then 0 else if e1ok then 1 else -1)
if c <> 0 then c else
if not e1ok || not e2ok then 0
else
let c = f e1.Current e2.Current
if c <> 0 then c else
go ()
go()
Now, you can send an email to fsbugs (@ microsoft.com) and ask them to remove the type constraint in the next F# release.
精彩评论