Search code examples
performancehaskellgadtexistential-type

Can GADTs (or existentials) without constraints be compiled as tight as untyped ordinary ADTs?


Suppose I have some ADT, like

data Foo = Foo !Int
         | Bar (Int->Int) Foo

Now say I want to impose some kind of extra type safety, getting rid of the "magic number type":

{-# LANGUAGE GADTs #-}

newtype Intey a = Intey { getIntey :: Int }

data Foo' a where
   Foo :: !(Intey a) -> Foo' a
   Bar :: (Intey a -> Intey b) -> Foo' a -> Foo' b

Since b is just a phantom argument within the constructor, has no constraints or anything else, it is basically meaningless – except for the type checker. Can it therefore compile down to the same as Foo, without any performance etc. cost?


Solution

  • You'd need to look at the Core to be absolutely sure, but in general:

    • newtype has no runtime cost compared to the underlying type. However something like map getIntey will still traverse the list doing nothing.

    • Types and type parameters themselves are erased during compilation so should also have no runtime cost - this is one of the advantages of static typing. It's only if you use a type class that a runtime value might be passed around.

    So in most cases you can expect the same performance, but you may need to be a little careful about operations on containers like lists.

    If you restrict yourself to GHC 7.8, then the new coerce function can help with that too.