Haskell に組み込まれた言語を扱っています。私の言語はソース コードとして印刷できるので、Compile
クラスを作成し、印刷できるすべてのプログラム要素のクラス インスタンスを作成しました。そうすれば、コードを構成的にダンプできます。モードの概念が考慮される前に、これはうまくいきました。
各言語は 2 つのモードで使用できます ( class のインスタンスとして実装されます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
表現のみに使用