malcolmwallace / cpphs

The C pre-processor, implemented in Haskell.
2 stars 0 forks source link

CPPHS fails to substitute constant #25

Open LeventErkok opened 3 years ago

LeventErkok commented 3 years ago

This program:

{-# LANGUAGE CPP                  #-}
{-# LANGUAGE DataKinds            #-}
{-# LANGUAGE KindSignatures       #-}
{-# LANGUAGE TypeOperators        #-}
{-# LANGUAGE TypeFamilies         #-}
{-# LANGUAGE UndecidableInstances #-}

import Data.Kind
import Data.Type.Equality
import GHC.TypeLits

#define N 2

type family V (e :: Nat) :: Constraint where
  V (e :: Nat) = (e `CmpNat` N ~ 'EQ, e `CmpNat` N ~ 'LT)

fails to generate a correctly expanded output, thus causing compilation failure down the line.

The relevant part of the expanded output is:

type family V (e :: Nat) :: Constraint where
  V (e :: Nat) = (e `CmpNat` 2 ~ 'EQ, e `CmpNat` N ~ 'LT)

Notice that CPPHS substituted for the first occurrence of N, but not the second. Most likely it's getting confused by the occurrence of two ' characters, and leaving whatever is inside untouched. But that's not a valid Haskell character, so I would've expected this to work correctly.

There's a simple work-around by putting the second part in a line by itself:

  V (e :: Nat) = ( e `CmpNat` N ~ 'EQ
                 , e `CmpNat` N ~ 'LT)

in which case the expansion correctly replaces N in both lines.

So, there's a work around; but would be nice if it wasn't needed.