2013-08-08 11 views
7

私はHaskellに埋め込まれた言語で作業しています。私の言語はソースコードとして印刷することができるので、Compileクラスを作成し、印刷可能なすべてのプログラム要素に対してクラスインスタンスを作成しました。そうすれば、コードを構成的にダンプすることができます。これは、モードの概念が考慮される前にうまくいきました。Haskell:インスタンスの不正な型同義語ファミリアプリケーション

各言語は2つのモード(クラス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" 

タイプ同義語ファミリがクラスでうまく動作しないことがわかっているので、別の解決策を探しています。私の知る(ただし、使用したくない)

考えられる解決策:

  • 使用する複数の機能の代わりに、単一多型comp機能。
  • のみを使用しNamedMode表現

答えて

3

私の友人のために、ゾルターン・ケレメンは私に解決策を送りました。彼はラッパークラスを使用して、指定された言語のプログラム要素をカプセル化しました。このようにして、必要以上にオーバーヘッドをかけずにインスタンス・ヘッドからタイプ・ファミリー・アプリケーションを削除しました。

私は他のソリューションも探しています。また

{-# 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" 
+0

この他の質問との類似点に言及してくれてありがとう:http://stackoverflow.com/questions/2590495/problem-when-mixing-type-classes-and-type-families?rq=1 –

+0

はでしたデータの代わりにnewtypeを使用しました - いいえ? – lynnard

関連する問題