Haskell : Illegal type synonym family application in instance

I'm working with languages embedded in Haskell. My languages can be printed out as source code, so I created a Compile class and made a class instance for every program element that can be printed out. That way I could dump my code compositionally. This worked fine before the concepts of modes was considered.

Each language can be used in two modes (implemented as instances of class Mode ). In simple mode everything is normal. In named mode a lot of program elements can be replaced with strings. (It works like macro definitions.)

I want to keep all representations type-safe. So program elements of different langauges or different modes cannot be mixed.

So the problem is: how to dump the languages regardless of the mode?

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}
class Compile a where
  comp :: a -> String

-- common elements in all languages
data ElemA l m = ElemA (ElemB l m)
data ElemB l m = ElemB

class Lang l where
  -- language-specific elements
  data Instructions l :: * -> *

-- common modes for all languages
class Mode l m where
  type MElemA l m :: *
  type MElemB l m :: *

-- mode with normal program elements
data SimpleMode
instance Mode l SimpleMode where
  type MElemA l SimpleMode = ElemA l SimpleMode
  type MElemB l SimpleMode = ElemB l SimpleMode

-- a mode where each program element can be replaced with a string
data NamedMode
instance Mode l NamedMode where
  type MElemA l NamedMode = Either String (ElemA l NamedMode)
  type MElemB l NamedMode = Either String (ElemB l NamedMode)

-- definition of Lang1 language
data Lang1
instance Lang Lang1 where
  data Instructions Lang1 m 
    = Add (MElemA Lang1 m) (MElemA Lang1 m) (MElemA Lang1 m)
    | Mul (MElemA Lang1 m) (MElemA Lang1 m) (MElemA Lang1 m)
    -- | ...

-- dumping the source code of Lang1 langauge

-- ILLEGAL TYPE SYNONYM FAMILY APPLICATION HERE
instance Compile (MElemA Lang1 m) where  
  comp _ = "A"
-- AND HERE
instance Compile (MElemB Lang1 m) where  
  comp _ = "B"

I know that type synonym families does not work well with classes, so I'm looking for another solution.

Possible solutions I'm aware of (but don't want to use):

  • Use multiple functions instead of a single polymorphic comp function.
  • Use only NamedMode for representation

  • A friend of mine, Zoltán Kelemen sent me a solution. He used wrapper classes to encapsulate a program element of a specified language. This way he had eliminated type family applications from the instance heads without more overhead than necessary.

    I'm also looking for other solutions.

    {-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
    class Compile a where
      comp :: a -> String
    
    -- common elements in all languages
    data ElemA l m = ElemA (ElemB l m)
    data ElemB l m = ElemB
    
    class Lang l where
      -- language-specific elements
      data Instructions l :: * -> *
    
    -- wrapper classes for program elements of Lang1
    data Lang1A m = WrapperA (ElemA Lang1 m)
    data Lang1B m = WrapperB (ElemB Lang1 m)
    
    -- common modes for all languages
    class Mode l m where
      type MElemA l m :: *
      type MElemB l m :: *
    
    -- mode with normal program elements
    data SimpleMode
    instance Mode l SimpleMode where
      type MElemA l SimpleMode = ElemA l SimpleMode
      type MElemB l SimpleMode = ElemB l SimpleMode
    
    -- a mode where each program element can be replaced with a string
    data NamedMode
    instance Mode l NamedMode where
      type MElemA l NamedMode = Either String (ElemA l NamedMode)
      type MElemB l NamedMode = Either String (ElemB l NamedMode)
    
    -- definition of Lang1 language
    data Lang1
    instance Lang Lang1 where
      data Instructions Lang1 m 
        = Add (MElemA Lang1 m) (MElemA Lang1 m) (MElemA Lang1 m)
        | Mul (MElemA Lang1 m) (MElemA Lang1 m) (MElemA Lang1 m)
        -- | ...
    
    -- dumping the source code of Lang1 langauge
    
    -- ILLEGAL TYPE SYNONYM FAMILY APPLICATION HERE
    instance Compile (Lang1A m) where  
      comp (WrapperA e) = "A"
    -- AND HERE
    instance Compile (Lang1B m) where  
      comp (WrapperB e) = "B"
    
    链接地址: http://www.djcxy.com/p/15104.html

    上一篇: NEW是内部专有API

    下一篇: Haskell:实例中的非法类型同义词族应用程序