我正在使用嵌入在 Haskell 中的语言。我的语言可以作为源代码打印出来,所以我创建了一个Compile
类并为每个可以打印的程序元素创建了一个类实例。这样我就可以组合地转储我的代码。在考虑模式的概念之前,这很好用。
每种语言都可以在两种模式下使用(实现为 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
用于表示