2

甚至问这个我都觉得很傻,因为它看起来很琐碎,但我的大脑让我失望了。如果我有以下情况:

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

是否有一种优雅的方法来确定 a、b 和 c 是否都具有相同的值。就像是:

let result = (a = b = c)

这失败了,因为表达式a = b返回 true 并且下一个表达式导致true = c并抱怨它期待 int,而不是 bool。我唯一能想到的是:

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

当我想添加更多变量时,这将不起作用。

我真正想做的是:

let same (x: string * string * string) =
    match x with
    | (a, a, a) -> true
    | _ -> false

我希望我可以将所有元素匹配到一个元素中,如果它们不同,它将继续前进,但它在匹配中的第二个元素上表示它已经被绑定。

4

4 回答 4

8

要检查列表中的每个值是否相同:

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

用法

let a, b, c = 1, 1, 1
same [a; b; c] //true
于 2012-07-13T20:38:33.070 回答
2
let same (a, b, c) = a = b && b = c
于 2012-07-13T20:11:31.893 回答
2

我会尝试使用 forall 函数来确定所有数字是否相同。

let list = [a; b; c;];;
List.forall (fun n -> n = a) list;;
val it : bool = true
于 2012-07-15T08:34:18.947 回答
2

此解决方案准确生成所需的语法。令我惊讶的是,速度相当快。此外,这似乎是使用单子的一个很好的例子,也称为计算表达式

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

这个怎么运作

该方法是一个非常简化的State monad。monadic 类型是 的元组(bool, 'T)。第一个组件是正在进行的计算的布尔值,第二个是要比较的样本值。

(==)将初始化 monad,类似于Delay运算符。
(&=)用于所有后续比较。它类似于Bind运算符。
我们不需要Return,因为fst会很好用。
mOp1并且mOp2是对逻辑操作的抽象。这些允许定义您自己的运算符。以下是or-equal和的示例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

表现

我真的很喜欢@ildjarn 的漂亮解决方案,但是构建List速度很慢,所以我的主要目标是性能。
运行 8 次比较链,1000 万次:

  • 04972msa=b && a=с && ...
  • List基于23138ms
  • 12367ms 一元
于 2012-07-19T00:40:21.957 回答