簡體   English   中英

以更實用的方式(scalaz)使用 Scala 會導致性能/可維護性損失嗎?

[英]Will using Scala in a more functional way (scalaz) incur a performance/maintainability penalty?

我目前正在研究一個小項目(< 10k loc),該項目主要是純粹的,但依賴於可變優化,主要基於迭代器和一些數據結構重用以進行重型計算。

我想學習更多的函數式編程並希望獲得更多的類型安全性,例如將可變計算包裝到 state 變壓器單子等中。 為此,存在 scalaz 庫。

問題一

當通過使用所有花哨的功能性東西在更大范圍內抽象我的計算時,我會引入我不會擺脫的性能殺手嗎? 就像我的計算在 Monads 中被包裹得很深?

問題二

考慮到 Scala 的有限類型推斷,這是否可行? 我目前正在與非常大的類型簽名作斗爭(可能是因為我不知道如何正確擺脫它們)。 我想更多的“功能”會引入更多這樣的樣板代碼。

免責聲明

我不是在質疑函數式方法是好是壞。 問 Haskell 這個問題是沒有意義的。 我質疑對 Scala 這樣做是否明智。

根據要求編輯:我的項目中的大型簽名示例

(但這將是一個不同的問題)

以下代碼描述了對類型參數化輸入 object ( DiscreteFactorGraph[VariableType, FactorType[VariableType]] ) 的迭代計算。 您可以使用createInitialState構造計算advanceState並使用 AdvanceState 對其執行計算,最后使用marginals從中提取一些信息。

我希望在計算期間保留因子圖 object (及其參數類型)的類型,以便marginals的最終應用產生正確類型的DiscreteMarginals[VariableType] 我認為目前我只需要在計算類型(即TState )中保留變量類型,因此不使用攜帶因子類型。 但在不同的地方,我什至需要DiscreteFactorGraph的類型是可變的,所以我傾向於在未來需要更多的類型信息通過計算。

我一直在擺弄這部分,我希望有更好的解決方案。 目前我有一個非常實用的方法,其中只有這三個功能。 但我必須通過它們鏈接類型。 或者,我可以將其定義為 class 並使用所有這些類型參數化 class,因此我不必為每種方法重復類型參數。

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])
}

關於問題一:

將計算包裝到 monads、applicatives、functors 和其他函數式 vodoo 中會產生一些開銷。 但是,將您的計算包裝到過程、方法、對象中也是如此。

問題的核心是,計算必須有多小,以便包裝開始變得明顯。 在不了解您項目的一些細節的情況下,沒有人會告訴您這一點。 然而,由於 Scala 的混合特性,您不必一直使用 go 單子。 很有可能將類似 scalaz 的樣式用於更高級別的計算組合,並在性能需要時使用本地包含的可變 state。

關於問題二:

由於我不知道您的類型簽名的性質,因此 scalaz 是否會通過泛化計算來幫助您,或者您是否必須圍繞 Scala 對部分類型構造函數應用程序的有限支持進行鍵入。

如果您的類型簽名 go 失控,我建議您嘗試在 package object 中聲明類型別名並使用它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM