В настоящее время я работаю над небольшим проектом (< 10k loc), который в основном чист, но использует измененные оптимизации, в основном основанные на итераторах и повторное использование структуры данных для сверхмощных вычислений.
Я хотел бы узнать немного более функциональное программирование и хочу получить больше безопасности типа, например. обертывание изменчивых вычислений в монады трансформатора состояния и тому подобное. Для этого существует библиотека scalaz.
Вопрос 1
При абстрагировании моих вычислений в более широком масштабе, используя все фантастические функциональные вещи, я буду вводить убийцы производительности, от которых я не избавлюсь? Например, когда мои расчеты завернуты глубоко в колени в Монадах?
Вопрос второй
Насколько это возможно, учитывая 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])
}