开发者

Performance implications of using GADTs

开发者 https://www.devze.com 2023-02-19 09:14 出处:网络
When answering a question with a suggestion to use GADTs, some questions with regards to performance came up in the comments. The question involved a typeclass PlotValue:

When answering a question with a suggestion to use GADTs, some questions with regards to performance came up in the comments. The question involved a typeclass PlotValue:

class PlotValue a where
    value :: a -> Double

and my answer suggested using a GADT Input:

data Input where
    Input :: (PlotValue a, PlotValue b) => Maybe a -> Maybe b -> Input

but the details are, I suppose, immaterial.

I'm wondering about two aspects of performance:

Time: Are there any runtime costs incurred by a pattern match like

case x of
    Input (Just a) (Just b) -> value a * value b
    _ -> 0.0

over and above the normal costs matching two Maybe values?

Space: How much storage overhead does a value of type Input carry? My guess is that it carries the two PlotValue dictionaries around for each and every value of type Input (a 'pointer' each?), meaning that a [Input] will be much more inefficient in terms of memory use than using (Just Double, Just Double) or, better yet, (# #Double, #Double #) - if you store the results of value in a normal or unpacked tuple.

So, while I love the expressiveness GADTs give me, I've never thought about the performance aspects 开发者_运维问答much. Can anyone tell me more about this (and any other hidden costs I might not be aware of)?


I think you've nailed down the overheads. For each existentially qualified variable you need the corresponding (pointer to) dictionaries. This takes space, and worse, the method calls are going to be slow. The (*) in your example will be an indirect function call, whereas with Double it would have been a primitive op.

0

精彩评论

暂无评论...
验证码 换一张
取 消