Is there a way to do multiple comparisons of inline values?

I feel stupid, even asking about it, because it seems so trivial, but my brain fails. If I had the following:

let a, b, c = 1, 1, 1 

Is there a suitable way to determine if a, b, and c all have the same value. Sort of:

 let result = (a = b = c) 

This fails because the expression a = b returns true, and the next expression is expressed in true = c and complains that it expected an int, not a bool. The only thing I can think of:

 a = b && a = c && b = c 

which will not work when I want to add more variables.

I am actually trying to do the following:

 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, he would move on, but he said on the second element in the match that he was already attached.

+2
source share
4 answers

To check if each value in the list is the same:

 let rec same = function | x::y::_ when x <> y -> false | _::xs -> same xs | [] -> true 

Using

 let a, b, c = 1, 1, 1 same [a; b; c] //true 
+8
source
 let same (a, b, c) = a = b && b = c 
+2
source

I would try using the forall function to determine if all numbers match.

 let list = [a; b; c;];; List.forall (fun n -> n = a) list;; val it : bool = true 
+2
source

This solution creates the exact syntax you need. Surprising to me, pretty fast. Also, this is apparently a good example of using monads, also known as Expression Calculations .

 // 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

This approach is a very simplified state monad. The monadic type is a tuple (bool, 'T) . The first component is the logical value of the current calculation, and the second is an approximate value for comparison.

(==) will initialize a monad similar to the Delay statement.
(&=) used for all subsequent comparisons. It is similar to the Bind statement.
We do not need Return , because fst will work very well.
mOp1 and mOp2 are abstractions of logical operations. They allow you to define 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 liked the beautiful solution from @ildjarn, but building the List pretty slow, so my main goal was performance.
Running a chain of 8 comparisons, 10 million times:

  • 04972ms a=b && a= && ...
  • 23138ms List Based
  • 12367ms monadic
+2
source

Source: https://habr.com/ru/post/1494000/


All Articles