Data Constructor promotion in GHC-7.6

HaskellConstructorGhc

Haskell Problem Overview


I had this code:

class SymbolSet tpe where
  data Symbol tpe :: *
 
data SSet tpe where
  Identity :: tpe -> SSet tpe
  And :: SSet tpe -> Symbol tpe -> SSet tpe
 
class HasElem a b where
 
instance (SymbolSet tpe) => HasElem (And (Identity tpe) s) s
instance (HasElem sset s) => HasElem (And sset s) s

which was compiling in GHC-7.4. However on moving to GHC-7.6 it started giving compilation errors:

'And' of tpe `forall tpe. tpe -> Symbol * tpe -> SSet tpe' is not promotable

on digging through the docs, I found a new clause added to "Datatype Promotion" pages in GHC-7.6 vs GHC-7.4

> We do not promote datatypes whose constructors are kind polymorphic, > involve constraints, or use existential quantification.

My question is:

  1. What is the rationale behind not promoting such constructors?
  2. What would be the correct way of doing it?

Haskell Solutions


Solution 1 - Haskell

You didn't say which version of GHC 7.6 you were using or include which extensions you have on, so I'm guessing a bit.

This ticket seems to answer your question 1, although I don't totally understand the problem myself. In your particular example, I think SSet isn't promotable because one of its arguments (Symbol tpe) is an associated type which brings with it the SymbolSet constraint.

If I move Symbol out of the class we get the type promoted, however now we get kind mismatch errors:

{-# LANGUAGE DataKinds , TypeFamilies , GADTs , MultiParamTypeClasses #-}
class SymbolSet tpe where
  -- data Symbol tpe :: *
data Symbol tpe :: *
-- ...

I can get the whole shebang to compile by adding kind signatures to HasElem:

{-# LANGUAGE DataKinds , TypeFamilies , GADTs , MultiParamTypeClasses, FlexibleInstances  #-}
class SymbolSet tpe where
-- MOVED OUT OF CLASS:
data Symbol tpe :: *

data SSet tpe where
  Identity :: tpe -> SSet tpe
  And :: SSet tpe -> Symbol tpe -> SSet tpe

-- ADDED KIND SIGNATURES:
class HasElem (a :: SSet *) (b :: Symbol *) where

instance (SymbolSet tpe) => HasElem (And (Identity tpe) s) s
instance (HasElem sset s) => HasElem (And sset s) s

I don't really understand your code so that may not work for you.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrabisgView Question on Stackoverflow
Solution 1 - HaskelljberrymanView Answer on Stackoverflow