scala - 是否有任何记录在案的函数式编程反模式?

标签 scala haskell f# functional-programming anti-patterns

就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the help center寻求指导。




9年前关闭。




下个月我将从事一个新的研发项目,该项目将采用函数式编程语言(我投票支持 Haskell,但现在 F# 获得了更多共识)。现在,我已经使用这些语言一段时间,并用它们开发了一些命令行工具,但这是一个相当大的项目,我正在努力提高我的函数式编程知识和技术。我也阅读了很多关于该主题的内容,但我找不到任何记录函数式编程世界中反模式的书籍或资源。
现在,学习反模式意味着 了解其他聪明人的失败 :在 OOP 中,我知道其中的一些,并且当通常是反模式的东西完全符合我的需求时,我有足够的经验来明智地选择。但我可以选择这个,因为我知道其他聪明人吸取的教训。
因此,我的问题是:有没有 记录 anti-patterns在函数式编程中?到目前为止,我所有的同事都告诉我他们不知道,但他们无法说明原因。

  • 如果是,请包含一个指向权威来源(目录、论文、书籍或同等 Material )的链接。
  • 如果没有,请通过 a proper theorem 支持您的回答.

  • don't turn this question in a list :这是一个 bool 问题,只需要一个证明来评估答案。例如,如果您是 Oleg Kiselyov,"is"就足够了,因为每个人都可以找到您关于该主题的文章。不过,请大方一点。
    请注意,我正在寻找正式的反模式,而不是简单的坏习惯或坏做法。
    来自 linked wikipedia article on Anti-Patterns :

    ... there must be at least two key elements present to formally distinguish an actual anti-pattern from a simple bad habit, bad practice, or bad idea:

    1. some repeated pattern of action, process or structure that initially appears to be beneficial, but ultimately produces more bad consequences than beneficial results, and
    2. an alternative solution exists that is clearly documented, proven in actual practice and repeatable.

    此外,“记录在案”是指来自 的内容。权威作者知名来源 .
    我习惯的语言是:
  • Haskell(我真的开始认为如果代码编译,它就可以工作!)
  • 斯卡拉
  • F#

  • 但我也可以调整有关以其他功能语言记录的反模式的知识。
    我在网上搜索了很多,但我找到的所有资源要么与 OOP 相关,要么与函数布局相关(在函数开头定义变量,等等......)。

    最佳答案

    我见过的唯一反模式是过度单子(monad)化,因为单子(monad)非常有用,所以它介于不良实践和反模式之间。

    假设你有一些属性(property) P你希望你的某些对象是真实的。你可以用 P monad 来装饰你的对象(在 Scala 中,使用 REPL 中的 paste 来让对象和它的伙伴粘在一起):

    class P[A](val value: A) {
      def flatMap[B](f: A => P[B]): P[B] = f(value)       // AKA bind, >>=
      def map[B](f: A => B) = flatMap(f andThen P.pure)   // (to keep `for` happy)
    }
    object P {
      def pure[A](a: A) = new P(a)                        // AKA unit, return
    }
    

    好的,到目前为止一切顺利;我们骗了一点 value一个 val而不是让它成为一个comonad(如果这是我们想要的),但我们现在有一个方便的包装器,我们可以在其中包装任何东西。现在假设我们还有属性 QR .
    class Q[A](val value: A) {
      def flatMap[B](f: A => Q[B]): Q[B] = f(value)
      def map[B](f: A => B) = flatMap(f andThen Q.pure)
    }
    object Q {
      def pure[A](a: A) = new Q(a)
    }
    class R[A](val value: A) {
      def flatMap[B](f: A => R[B]): R[B] = f(value)    
      def map[B](f: A => B) = flatMap(f andThen R.pure)
    }
    object R {
      def pure[A](a: A) = new R(a) 
    }
    

    所以我们装饰我们的对象:
    class Foo { override def toString = "foo" }
    val bippy = R.pure( Q.pure( P.pure( new Foo ) ) )
    

    现在我们突然面临一大堆问题。如果我们有一个方法需要属性 Q ,我们如何得到它?
    def bar(qf: Q[Foo]) = qf.value.toString + "bar"
    

    嗯,很明显bar(bippy)行不通。有traverseswap有效地翻转 monad 的操作,所以我们可以,如果我们定义 swap以适当的方式,做类似的事情
    bippy.map(_.swap).map(_.map(bar))
    

    取回我们的字符串(实际上是 R[P[String]] )。但是我们现在已经 promise 为我们调用的每个方法做类似的事情。

    这通常是错误的做法。如果可能,您应该使用其他一些同样安全的抽象机制。例如,在 Scala 中,您还可以创建标记特征
    trait X
    trait Y
    trait Z
    val tweel = new Foo with X with Y with Z
    def baz(yf: Foo with Y) = yf.toString + "baz"
    baz(tweel)
    

    哇!容易多了。现在非常重要的是要指出并非一切都更容易。例如,如果您开始操作 Foo,则使用此方法您必须自己跟踪所有装饰器,而不是让单子(monad) map/flatMap为你而做。但是很多时候你不需要做一堆实物操作,那么深度嵌套的 monad 就是一种反模式。

    (注意:monadic 嵌套具有堆栈结构,而特征具有 set 结构;编译器没有内在的原因不能允许 set-like monad,但它不是典型的类型理论公式的自然构造。反模式是一个简单的结果是深堆栈难以使用。如果您为 monad(或 Haskell 中的标准 Monad 转换器集)实现所有 Forth 堆栈操作,它们可能会更容易一些。)

    关于scala - 是否有任何记录在案的函数式编程反模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15848856/

    相关文章:

    scala - 隐式类中的方法重载

    haskell - 为什么关联类型同义词不暗示约束

    haskell - LFSR 实现中的高效位摆弄

    F# 如果为 null,则返回空字符串

    dictionary - F#:在计时器上将项目添加到字典

    java - Windows : <console>:16: error: not found: value sqlContext 中的 Spark 失败

    scala - "User did not initialize spark context"在 SPARK YARN 集群模式下使用 Scala 代码时出错

    performance - 句子词形还原的最快方法

    function - Haskell 哪个函数可以对每个 n 进行分组,使得::[a] -> Int -> [[a]]

    list - 如何使用 List.map 实现 List.allPairs?