Подтвердить что ты не робот

Будет ли использование Scala более функциональным способом (скаляз) повлечь за собой штраф за производительность/ремонтопригодность?

В настоящее время я работаю над небольшим проектом (< 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])
}
4b9b3361

Ответ 1

Что касается первого вопроса:

Будет наложенным накладные расходы путем переноса ваших вычислений на монады, аппликаторы, функторы и другие функциональные vodoo. Но и перенос ваших вычислений в процедуры, методы, объекты.

Вопрос состоит в том, насколько малым является вычисление, чтобы обертывание стало заметным. Это то, что вам никто не скажет, не зная подробностей вашего проекта. Однако из-за гибридной природы Scala вам не нужно идти на монады до конца. Вполне возможно использовать стиль, похожий на сказус, для композиций более высокого уровня ваших вычислений и использовать локально измененное состояние, в котором это требует производительность.

Что касается второго вопроса:

Поскольку у меня нет понятия о характере сигнатур вашего типа, если сказаз поможет вам, обобщая вычисления, или вам придется набирать путь вокруг Scala ограниченной поддержки для приложения-конструктора с частичным типом.

Если ваши сигнатуры типа выходят из-под контроля, я предлагаю вам попытаться объявить псевдоним типа в объекте пакета и использовать их.