F# 消除F中重复匹配逻辑的技术#

F# 消除F中重复匹配逻辑的技术#,f#,F#,在设计联合类型层次结构时,似乎存在大量逻辑重复的可能性。对于一个简单且有点做作的例子,考虑下面的类型,表示“灵活”的数字: 其他运算符将包含类似的重复匹配逻辑。是否有一种模式/实践可用于将逻辑整合到一个功能中,以消除此类冗余 (注意:我意识到在F中有更好的处理泛型算法的方法;这个例子应该被视为模式匹配中“我如何停止重复我自己?”问题的一个例子)你可以抽象出(+)和()编写一个函数,将整数和浮点算术运算符作为参数: static member binOp (intOp : int -> in

在设计联合类型层次结构时,似乎存在大量逻辑重复的可能性。对于一个简单且有点做作的例子,考虑下面的类型,表示“灵活”的数字:

其他运算符将包含类似的重复匹配逻辑。是否有一种模式/实践可用于将逻辑整合到一个功能中,以消除此类冗余


(注意:我意识到在F中有更好的处理泛型算法的方法;这个例子应该被视为模式匹配中“我如何停止重复我自己?”问题的一个例子)

你可以抽象出
(+)
()
编写一个函数,将整数和浮点算术运算符作为参数:

static member binOp (intOp : int -> int -> int) (floatOp : float -> float -> float) (x : Number, y:Number) =
    match x,y with
    |Integer(x), Integer(y) -> Integer(intOp x y)
    |Integer(x), Real(y) -> Real(floatOp (float x) y)
    |Real(x), Integer(y) -> Real(floatOp x (float y))
    |Real(x), Real(y) -> Real(floatOp x y)

static member (+) (x,y) = Number.binOp (+) (+) (x,y)
static member (-) (x,y) = Number.binOp (-) (-) (x,y)
同样的函数也适用于
(*)
。但是,当您进入
(/)
时,模式开始崩溃,因为您可能想要浮点结果,即使对于整数输入也是如此

根据我的经验,仅仅使用复制通常更简单——在实践中通常并没有那个么糟糕,试图抽象太多会导致无法阅读的代码


在某些情况下,单个模式匹配情况变得相当复杂,可以帮助您抽象一次模式。我认为它们在您的具体示例中没有意义,但它们值得记住。

绑定到相同变量时的小技巧:
|Integer(I),Real(r)|Real(r),Integer(I)->Real(floatOp(float I)r)
这只适用于像
(+)
,而不是
static member binOp (intOp : int -> int -> int) (floatOp : float -> float -> float) (x : Number, y:Number) =
    match x,y with
    |Integer(x), Integer(y) -> Integer(intOp x y)
    |Integer(x), Real(y) -> Real(floatOp (float x) y)
    |Real(x), Integer(y) -> Real(floatOp x (float y))
    |Real(x), Real(y) -> Real(floatOp x y)

static member (+) (x,y) = Number.binOp (+) (+) (x,y)
static member (-) (x,y) = Number.binOp (-) (-) (x,y)