I wonder which of the two strategies below is the most efficient for overloading a function (here the function teX in my example).
Using data
and pattern matching:
data TeX
= TeXt String
| TeXmath String
deriving (Show,Read,Eq)
teX (TeXt t) = t
teX (TeXmath t) = "$$" ++ t ++ "$$"
Or using a bit of abstraction:
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 ++ "$$"
Surely the first is easier to use and the second easier to enrich; but I wonder if one will run faster than the other, or if Haskell will implement them in the exact same way.
The first one is more space-efficient. Calling a function defined in a type class is equivalent to invoking a method in an object-oriented language: any functions which are polymorphic on the type TeX t
(i.e., has TeX t =>
in the type signature) will have to carry around an extra, implicit parameter, namely a dictionary storing the particular methods for a given instance of TeX
.
Now, about faster? I'd imagine that for programs with a small memory footprint, the first way is marginally faster due to less memory allocation and one less indirection to actually calling the teX
function. For allocation-heavy programs, the same would hold until the program hits some memory allocation threshold—which the first version would hit later, and would therefore be somewhat faster once the 2nd one hits that point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With