【问题标题】:Is is possible to pattern match on the underlying shape of a discriminated union?是否可以在有区别的联合的基础形状上进行模式匹配?
【发布时间】:2016-03-24 23:46:08
【问题描述】:

F# 是否支持通过 Identifier pattern 以外的条件对已区分的联合成员实例进行模式匹配?

例如,假设我想匹配数据的底层形状,并且我想考虑任何具有int * int 形状的东西,而不管 DU 如何对值进行分类。是

这是我现在的做法:

type ExampleDU = 
  | BinaryCase1 of x:int * y:int
  | BinaryCase2 of x:int * y:int
  | UnaryCase1  of x:int

let underlyingValue = (1,2)
let asCase1 = BinaryCase1 underlyingValue
let asCase2 = BinaryCase2 underlyingValue

let shapeName = 
  match asCase1 with
  | BinaryCase1 (x,y) | BinaryCase2 (x,y) -> "pair" // is this possible without explicitly writing the name for each part?
  | _ -> "atom"

我想要更接近以下的内容:

let shapeName = 
  match asCase1 with
  | (x,y) -> "pair" 
  | _ -> "atom"

F# 目前是否支持某些类似的表达语法,或者我是否坚持明确指定所有情况?

注意:我知道我可以通过反射找出我想要的信息,但我对这样的解决方案不感兴趣。

【问题讨论】:

  • 您可以为此使用主动模式 - 但它不能轻易地表达出来
  • @JohnPalmer 您对使用带有可区分联合的活动模式有任何参考吗?我可能会从示例用法中弄清楚如何做我想做的事
  • 为什么要这样做?两个箱子的形状相似的事实应该完全是偶然的。 DU 的全部意义在于……嗯……区分互斥的情况。 根据定义,两种不同的情况没有任何共同之处,尽管有时它们看起来具有相同的形状。
  • @MarkSeemann DU 的成员是互斥的。这意味着不存在作为多于一个 DU 成员的实例的对象。但是,“两个不同的案例没有共同点”太强了。您似乎在断言不相交联合的定义要求不同成员的实例不能共享公共属性。我很确定那是错误的。实际上,DU 的不同成员的实例很可能会共享属性,原因与它们在同一范围内声明的原因相同。
  • @MarkSeemann 我在不同的 DU 成员之间识别共同形状的目的是经济地处理其实例的共享属性。

标签: f# functional-programming pattern-matching discriminated-union active-pattern


【解决方案1】:

这是活动模式答案

let (|Pair|_|) input = 
    match input with
    |BinaryCase1(a,b)
    |BinaryCase2(a,b) -> Some(a,b)
    | _ -> None

及用法

match asCase1 with |Pair(a,b) -> printfn "matched" | _ -> ();;

【讨论】:

  • 我明白了 - 但看起来这种方法仍然需要枚举每个案例并分配形状的代码(每个可区分联合的活动模式)。或者,您是否建议将其推广到更可跨不同 DU 类型重用的东西?
  • 这根本不能一概而论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
  • 2016-11-12
  • 2013-06-27
  • 2018-11-24
  • 2023-03-16
  • 1970-01-01
  • 2014-05-07
相关资源
最近更新 更多