Significant difference in memory usage between Type Application and Type Signature
Summary
Using relatively large/complex types as arguments in type applications compiles significantly faster and using significantly less memory than when using type signatures. In testing, the example below requires around 41.5MB of memory when using type applications and compiles instantly, while it requires approximately 3.55GB of memory when using a type signature.
Steps to reproduce
Compile the code below, with one of the two equations of test
given. With the type application, it will compile in a short amount of time with low memory usage, but compiling with the type signature will cause a massive rise in compilation time and memory usage.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE RankNTypes #-}
import Data.Proxy
import GHC.TypeLits
data MyNat = Z | S MyNat
data Vector (n :: MyNat) a where
Empty :: Vector Z a
Cons :: a -> Vector n a -> Vector (S n) a
type family Replicate (n :: MyNat) (a :: k) :: Vector n k where
Replicate Z x = Empty
Replicate (S n) x = Cons x (Replicate n x)
type family ToMyNat (n :: Nat) :: MyNat where
ToMyNat 0 = Z
ToMyNat n = S (ToMyNat (n-1))
type Simple = Replicate (ToMyNat 0) (Replicate (ToMyNat 0) Black)
type Large = Replicate (ToMyNat 200) (Replicate (ToMyNat 200) Black)
type Spec t = forall m . (t -> m) -> m
data Colour = White | Black
data Dec :: Vector n k -> Colour -> * where
Dec :: Dec v a
test :: Spec (Proxy (Dec Large Black))
-- test cont = cont (Proxy @(Dec Large Black))
test cont = cont (Proxy :: Proxy (Dec Large Black))
Using :kind!
in GHCi to evaluate Large
to a normal form completes relatively quickly.
Expected behavior
Using a type signature vs using a type application should have similar compilation times and memory usage.
Environment
- GHC version used: 8.8.4, 8.6.5
Optional:
- Operating System: Linux (POP!_OS), MacOS, Windows
- System Architecture: x86_64