Haskell中的有效重载

Haskell中的有效重载,haskell,Haskell,我想知道下面两种策略中哪一种对于重载函数(在我的示例中是函数teX)最有效 使用数据和模式匹配: data TeX = TeXt String | TeXmath String deriving (Show,Read,Eq) teX (TeXt t) = t teX (TeXmath t) = "$$" ++ t ++ "$$" 或者使用一点抽象: class TeX t where teX :: t -> String newtype TeXt = TeXt

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

  • 使用
    数据
    和模式匹配:

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

    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是否会以完全相同的方式实现它们。

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


    现在,快一点?我可以想象,对于内存占用很小的程序,第一种方法的速度稍微快一些,因为内存分配更少,实际调用
    teX
    函数的间接性也更少。对于分配量大的程序,这一点会一直保持,直到程序达到第一个版本稍后会达到的内存分配阈值,因此,一旦第二个版本达到该阈值,速度就会有所加快。

    第二个版本并不是TypeClass的真正含义,看起来您正试图在OOP中复制类您不应该以这种方式关注性能,而不是像呈现到
    String
    s这样的东西:这些本质上非常慢,因此类字典可能施加的任何开销都是可以忽略的。事实上,你真的不应该在这里渲染到
    String
    ,而应该渲染到(或者,duh)。例如,请参见由
    teX
    函数之类的函数呈现类型(githubpandoc repo)的方式后一个模块有点复杂,因为它涵盖的内容太多,但请注意,该方法具有可扩展性,而您所设想的类则没有:如何引入函数
    html::t->String”和
    markdown::t->String`以及类似的函数,如该包中其他地方定义的函数?我认为这个答案过于简化了。由于内联和类型专门化,很有可能在编译时完全解析
    TeX
    字典。至于性能,我想额外的间接性比分配有更大的影响。但我不会依赖我的直觉。这是真的,但从根本上说不是真的;人们可以(应该)努力工作以满足优化器的需求,但我不认为这是克服了使用类型类的基本开销,因为它无法得到可靠的保证。