Scala 模式匹配设计

Scala 模式匹配设计,scala,functional-programming,Scala,Functional Programming,我最近写了一些代码,比如下面的代码块,它让我想到,如果我对函数式编程抽象有更多的了解,设计可能会有所改进 sealed trait Foo case object A extends Foo case object B extends Foo case object C extends Foo . . . object Foo { private def someFunctionSemanticallyRelatedToA() = { // do stuff } private def

我最近写了一些代码,比如下面的代码块,它让我想到,如果我对函数式编程抽象有更多的了解,设计可能会有所改进

sealed trait Foo
case object A extends Foo
case object B extends Foo
case object C extends Foo
.
.
.

object Foo {
  private def someFunctionSemanticallyRelatedToA() = { // do stuff }
  private def someFunctionSemanticallyRelatedToB() = { // do stuff }
  private def someFunctionSemanticallyRelatedToC() = { // do stuff }
  .   
  .   
  .   

  def somePublicFunction(x : Foo)  = x match {
    case A => someFunctionSemanticallyRelatedToA()
    case B => someFunctionSemanticallyRelatedToB()
    case C => someFunctionSemanticallyRelatedToC()
    .
    .
    .
  }
}
我的问题是:

  • somePublicFunction()是否受到代码气味甚至整个设计的影响?我担心的是,值构造函数的列表可能会变得相当大
  • 是否有更好的FP抽象来更优雅甚至简洁地处理这种类型的设计

  • 你的解释太抽象了,不能给你一个自信的答案。但是,如果Foo的子类列表将来可能会增长/更改,我倾向于将其作为Foo的抽象方法,然后在子类中实现每种情况的逻辑。然后您只需调用Foo.myAbstractMethod(),多态性就能很好地处理一切

    这将使每个对象的特定代码与对象本身保持一致,从而使事情组织得更整齐。这还意味着您可以添加Foo的新子类,而无需跳转到代码中的多个位置来扩充代码中其他地方的现有匹配语句


    当子类集相对较小且固定时,案例类和模式匹配效果最好。例如,选项[T]只有两个子类,一些[T],没有。这永远不会改变,因为改变这一点将从根本上改变选项[T]所代表的内容。因此,它是模式匹配的一个很好的候选者。

    你的解释太抽象了,无法给你一个自信的答案。但是,如果Foo的子类列表将来可能会增长/更改,我倾向于将其作为Foo的抽象方法,然后在子类中实现每种情况的逻辑。然后您只需调用Foo.myAbstractMethod(),多态性就能很好地处理一切

    这将使每个对象的特定代码与对象本身保持一致,从而使事情组织得更整齐。这还意味着您可以添加Foo的新子类,而无需跳转到代码中的多个位置来扩充代码中其他地方的现有匹配语句

    当子类集相对较小且固定时,案例类和模式匹配效果最好。例如,选项[T]只有两个子类,一些[T],没有。这永远不会改变,因为改变这一点将从根本上改变选项[T]所代表的内容。因此,它是模式匹配的一个很好的候选者。

    您刚刚遇到了。在代码示例中,问题在于每次从
    Foo
    代数数据类型中添加或删除案例时,都可能需要根据
    Foo
    的值修改每个匹配项(如
    somePublicFunction
    )。在Nimrand的回答中,问题恰恰相反:您可以轻松地从
    Foo
    添加或删除案例,但每次您想要添加或删除行为(方法),您都需要修改
    Foo
    的每个子类

    有各种各样的建议来解决表达式问题,但一种有趣的函数方法是Oleg Kiselyov的,它用一个函数来替换代数数据类型的每种情况,该函数返回一些被认为与该情况等价的抽象值。使用泛型(即类型参数),这些函数都可以具有兼容的类型,并且无论何时实现,它们都可以相互协作。例如,我实现了一个使用TTFI构建和计算算术表达式树的示例:

    您刚刚遇到了。在代码示例中,问题在于每次从
    Foo
    代数数据类型中添加或删除案例时,都可能需要根据
    Foo
    的值修改每个匹配项(如
    somePublicFunction
    )。在Nimrand的回答中,问题恰恰相反:您可以轻松地从
    Foo
    添加或删除案例,但每次您想要添加或删除行为(方法),您都需要修改
    Foo
    的每个子类


    有各种各样的建议来解决表达式问题,但一种有趣的函数方法是Oleg Kiselyov的,它用一个函数来替换代数数据类型的每种情况,该函数返回一些被认为与该情况等价的抽象值。使用泛型(即类型参数),这些函数都可以具有兼容的类型,并且无论何时实现,它们都可以相互协作。例如,我实现了一个使用TTFI:

    有趣信息构建和评估算术表达式树的示例。我同意我的解决方案有相反的问题。然而,如果抽象方法集相对较小且不太可能经常更改,至少考虑到我们现在拥有的工具,这是一个很好的解决方案。有趣的信息。我同意我的解决方案有相反的问题。然而,如果抽象方法集相对较小且不太可能经常更改,那么至少考虑到我们现在拥有的工具,这是一个很好的解决方案。