【问题标题】:Efficient overloading in HaskellHaskell 中的高效重载
【发布时间】:2013-04-28 18:54:41
【问题描述】:

我想知道以下两种策略中哪一种对于重载函数最有效(在我的示例中是函数 teX)。

  1. 使用data 和模式匹配:

    data TeX
      = TeXt String
      | TeXmath String
      deriving (Show,Read,Eq)
    teX (TeXt t)    = t
    teX (TeXmath t) = "$$" ++ t ++ "$$"
    
  2. 或者使用一点抽象:

    class TeX t where
      teX :: t -> String
    
    newtype TeXt = TeXt String
      deriving (Show,Read,Eq)
    instance TeX TeXt where
      teX (TeXt t) = t
    
    newtype TeXmath = TeXmath String
      deriving (Show,Read,Eq)
    instance TeX TeXmath where
      teX (TeXmath t) = "$$" ++ t ++ "$$"
    

当然第一个更容易使用,第二个更容易丰富;但我想知道一个是否会比另一个运行得更快,或者 Haskell 是否会以完全相同的方式实现它们。

【问题讨论】:

  • 第二个并不是类型类的真正含义,看起来您正在尝试在 OOP 中复制类
  • 您不应该以这种方式关心性能,而不是像渲染到Strings 这样的事情:这些本质上是如此缓慢,以至于类字典可能施加的任何开销都可以忽略不计。事实上,你真的不应该在这里渲染到String,而应该渲染到Text(或LaTeX,呵呵)。
  • 我和 Arjan 在一起,第二个似乎是一个非常糟糕的主意。例如,请参阅 this one (githubpandoc repo)之类的类型由您的 teX 函数 here 之类的东西呈现的方式@
  • 后一个模块有点复杂,因为它涵盖了这么多,但请注意,该方法具有您设想的类所没有的可扩展性:您将如何引入函数html :: t -> String' and markdown :: t -> String` 和类似的函数,例如在该包的其他地方定义的?

标签: haskell


【解决方案1】:

第一个更节省空间。调用类型类中定义的函数等同于调用面向对象语言中的方法:任何在类型 TeX t 上具有多态性的函数(即,在类型签名中具有 TeX t =>)都必须携带一个额外的隐式参数,即存储TeX 给定实例的特定方法的字典。

现在,大约更快?我想,对于内存占用较小的程序,第一种方法会稍微快一些,因为内存分配更少,并且对实际调用 teX 函数的间接性也更少。对于分配繁重的程序,同样的情况会一直持续到程序达到某个内存分配阈值——第一个版本稍后会达到这个阈值,因此一旦第二个版本达到那个点,速度会更快。

【讨论】:

  • 我认为这个答案过于简单化了。由于内联和类型专门化,TeX 字典很可能会在编译时完全解析。至于性能,我猜额外的间接影响比分配大得多。但我不会依赖我的直觉。
  • 这是对的,但不是从根本上说对的;可以(应该)努力适应优化器的喜好,但我不认为这是克服使用类型类的基本开销,因为它不能得到可靠的保证。
猜你喜欢
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 2018-12-29
  • 1970-01-01
  • 1970-01-01
  • 2011-07-08
  • 2013-10-21
  • 2012-11-17
相关资源
最近更新 更多