是否会以更具功能性的方式使用Scala(scalaz)会导致性能/可维护性损失?

zig*_*tar 16 performance scala scalaz

我目前正在开发一个小型项目(<10k loc),它主要是纯粹的,但依赖于主要基于迭代器的可变优化和一些用于重载计算的数据结构重用.

我想学习更多功能编程,并希望通过例如将可变计算包装到状态变换器monad等中来获得更多类型安全性.为此目的,存在scalaz库.

问题一

当通过使用所有奇特的功能来大规模地抽象我的计算时,我会介绍我不会摆脱的性能杀手吗?就像我的计算被蒙纳德的膝盖深深地包裹起来一样?

问题二

考虑到Scala的有限类型推断,它是否可行?我目前正在与非常大的类型签名(可能因为我不知道如何正确摆脱它们).我认为更多"功能性"将引入更多这样的锅炉板代码.

放弃

我不是在质疑功能方法是好还是坏.向Haskell提出这个问题毫无意义.我在质疑Scala是否合情合理.

根据要求编辑:我的项目中的大型签名示例

(但这是一个不同的问题)

以下代码描述了对类型参数化输入对象(DiscreteFactorGraph[VariableType, FactorType[VariableType]])的迭代计算.你可以构造一个计算对象createInitialState并对其进行计算advanceState,最后从中提取一些信息marginals.

我希望在计算过程中保留因子图对象的类型(及其参数类型),以便最终的应用程序marginals产生正确的类型DiscreteMarginals[VariableType].我认为目前我只需要在计算类型(即TState)中保留变量类型,因此不使用携带因子类型.但是在不同的地方我甚DiscreteFactorGraph至需要变量的类型,所以我倾向于需要更多的类型信息在未来通过计算.

我很喜欢这部分,我希望有更好的解决方案.目前我有一个非常实用的方法,只有那三个功能.但我必须通过它们链接类型.或者,我可以将它定义为一个类,并使用所有这些类型对类进行参数化,因此我不必为每个方法重复类型参数.

object FloodingBeliefPropagationStepper extends SteppingGraphInferer {
  def marginals[V <: DiscreteVariable, F <: DiscreteFactor[V]](state: FloodingBeliefPropagationStepper.TState[V,F]): DiscreteMarginals[V] =
    BeliefPropagation.marginals(state._1, state._2)

  def advanceState[V <: DiscreteVariable, F <: DiscreteFactor[V]](state: FloodingBeliefPropagationStepper.TState[V,F]): FloodingBeliefPropagationStepper.TState[V,F] = {
    val graph = state._1
    (graph,
      BeliefPropagation.computeFactorMessages(
      graph,
      BeliefPropagation.computeVariableMessages(graph, state._2, graph.variables),
      graph.factors))
  }

  def createInitialState[V <: DiscreteVariable, F <: DiscreteFactor[V]](graph: DiscreteFactorGraph[V, F],
                                                                        query: Set[V],
                                                                        random: Random): FloodingBeliefPropagationStepper.TState[V,F] = {
    (graph,
      BeliefPropagation.computeFactorMessages(
      graph,
      BeliefPropagation.createInitialVariableMessages(graph, random),
      graph.factors))
  }

  type TState[V <: DiscreteVariable, F <: DiscreteFactor[V]] = (DiscreteFactorGraph[V,F],Map[(F,V),DiscreteMessage])
}
Run Code Online (Sandbox Code Playgroud)

MxF*_*xFr 5

关于问题一:

通过将计算包装到monad,applicatives,functor和其他功能性vodoo中会有一些开销.但是将计算包装到过程,方法,对象中也是如此.

问题的核心是,计算必须有多小,以便包装开始变得明显.如果不了解项目的某些细节,那就是没人会告诉你的.但是由于Scala的混合性质,你不必一直走下monad.很有可能将类似scalaz的样式用于计算的更高级别的组合,并使用性能需要它的本地包含的可变状态.

关于问题二:

由于我不知道你的类型签名的性质,如果scalaz会通过推广计算来帮助你,或者你将不得不键入Scala对部分类型构造函数应用程序的有限支持.

如果您的类型签名失控,我建议您尝试在包对象中声明类型别名并使用它们.