我目前正在从事一个小项目(< 10k loc),主要是纯编程,但是依赖于基于迭代器的可变优化和一些数据结构重用来进行重型计算。
我想学习更多函数式编程,并通过将可变计算包装成状态变换单子等方式获得更多类型安全性。为此存在scalaz库。
问题一
当使用所有花哨的功能性东西在更大范围上抽象我的计算时,是否会引入无法摆脱的性能杀手?例如,当我的计算在Monad中深深地包裹时?
问题二
考虑到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])
}
FloodingBeliefPropagationStepper.TState
这样非常长的名称。如果你想要高性能的解决方案,使用DiscreteVariable
而不是Int
或类似的东西可能会导致最大的性能损失(除非你实际上对变量做很少的操作)。到目前为止,代码看起来是为了最大化抽象而不是性能而编写的。那么你真的应该担心性能吗? - Rex KerrDiscreteVariable
只是变量本身的描述,并不持有任何状态(用于保存计算状态的具体数据结构是根据由图表描述的“问题说明”在较低级别上创建的)。实际上,您正在查看抽象类,而计算位于较低级别,例如BeliefPropagation
。 - ziggystar