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?
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.
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