我目前正在研究一个小项目(< 10k loc),该项目主要是纯粹的,但依赖于可变优化,主要基于迭代器和一些数据结构重用以进行重型计算。
我想学习更多的函数式编程并希望获得更多的类型安全性,例如通过将可变计算包装到状态转换器单子等中。为此,存在 scalaz 库。
问题一
当通过使用所有花哨的函数来更大规模地抽象我的计算时,我会引入我不会摆脱的性能杀手吗?就像我的计算在 Monads 中被包裹得很深?
问题二
考虑到 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])
}