2013-08-08 26 views
7

Tôi đang làm việc với các ngôn ngữ được nhúng trong Haskell. Ngôn ngữ của tôi có thể được in ra dưới dạng mã nguồn, vì vậy tôi đã tạo một lớp Compile và tạo một cá thể lớp cho mọi phần tử chương trình có thể được in ra. Bằng cách đó tôi có thể đổ mã của tôi một cách thành phần. Điều này làm việc tốt trước khi các khái niệm về chế độ được xem xét.Haskell: Ứng dụng gia đình từ đồng nghĩa không hợp lệ trong ví dụ

Mỗi ngôn ngữ có thể được sử dụng ở hai chế độ (được triển khai dưới dạng các thể hiện của lớp Mode). Trong chế độ đơn giản, mọi thứ đều bình thường. Ở chế độ có tên, rất nhiều phần tử chương trình có thể được thay thế bằng các chuỗi. (Nó hoạt động như định nghĩa macro.)

Tôi muốn giữ tất cả các biểu diễn an toàn loại. Vì vậy, các yếu tố chương trình của các ngôn ngữ khác nhau hoặc các chế độ khác nhau không thể được trộn lẫn.

Vì vậy, vấn đề là: làm thế nào để đổ các ngôn ngữ bất kể chế độ?

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

Tôi biết rằng các loại từ đồng nghĩa không hoạt động tốt với các lớp, vì vậy tôi đang tìm giải pháp khác.

giải pháp

Có thể tôi biết (nhưng không muốn sử dụng):

  • Sử dụng nhiều chức năng thay vì một đơn đa hình comp chức năng.
  • Chỉ sử dụng NamedMode cho đại diện

Trả lời

3

Một người bạn của tôi, Zoltán Kelemen đã gửi cho tôi một giải pháp. Ông đã sử dụng các lớp bao bọc để gói gọn một phần tử chương trình của một ngôn ngữ cụ thể. Bằng cách này, anh ta đã loại bỏ các ứng dụng gia đình kiểu từ những người đứng đầu thể hiện mà không tốn nhiều tiền hơn mức cần thiết.

Tôi cũng đang tìm các giải pháp khác.

{-# 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

Cũng nhờ đề cập đến những điểm tương đồng với câu hỏi này khác: http://stackoverflow.com/questions/2590495/problem-when-mixing-type-classes-and-type-families?rq=1 –

+0

Could đã sử dụng newtype thay cho dữ liệu - không? – lynnard

Các vấn đề liên quan