Повлечет ли использование Scala более функциональным способом (скаляр) снижение производительности / ремонтопригодности? - PullRequest
16 голосов
/ 17 августа 2011

В настоящее время я работаю над небольшим проектом (<10 тыс. Лок), который в основном чистый, но основывается на изменяемой оптимизации, в основном на основе итераторов и некоторого повторного использования структуры данных для сложных расчетов.</p>

Я хотел бы научиться немного более функциональному программированию и хотеть получить большую безопасность типов, например, оборачивая изменяемые вычисления в монады преобразователей состояний и тому подобное.Для этой цели существует библиотека scalaz.

Вопрос первый

Если абстрагировать мои вычисления в более крупном масштабе, используя все причудливые функциональные вещи, я представлю убийцы производительности, которых я не получуизбавиться от?Например, когда мои вычисления в Монадах обернуты до колен?

Вопрос второй

Реально ли это вообще, учитывая ограниченный вывод типа Scala?В настоящее время я борюсь с очень большими типами подписей (возможно, потому что я не знаю, как правильно избавиться от них).Я полагаю, что более «функциональный» вводит еще больше такого кода.

Отказ от ответственности

Я не подвергаю сомнению, является ли функциональный подход хорошим или плохим.Задавать этот вопрос для Хаскелла бессмысленно.Я спрашиваю, имеет ли смысл делать это для 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])
}

1 Ответ

5 голосов
/ 17 августа 2011

Относительно первого вопроса:

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

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

Относительно вопроса два:

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

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

...