Pracuję z językami osadzonymi w Haskell. Moje języki można wydrukować jako kod źródłowy, dlatego utworzyłem klasę Compile
i stworzyłem instancję klasy dla każdego elementu programu, który można wydrukować. W ten sposób mogłem skomponować mój kod. To działało dobrze zanim rozważano koncepcje trybów.Haskell: Nielegalna aplikacja rodziny synonimów w instancji
Każdy język może być używany w dwóch trybach (zaimplementowanych jako instancje klasy Mode
). W trybie prostym wszystko jest normalne. W nazwanym trybie wiele elementów programu można zastąpić ciągami. (Działa jak definicje makr.)
Chcę zachować wszystkie reprezentacje jako bezpieczne. Zatem nie można mieszać elementów programowych różnych języków lub różnych trybów.
Problem polega na tym, jak zrzucić języki bez względu na tryb?
{-# 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"
Wiem, że rodziny synonimów typu nie działają dobrze z klasami, więc szukam innego rozwiązania.
Możliwe rozwiązania Jestem świadomy (ale nie chcą używać):
- Używaj wielu funkcji zamiast pojedynczego polimorficzny
comp
funkcja. - Używaj tylko
NamedMode
reprezentacji
Również dzięki za wspomnieć podobieństwa z tym inne pytanie: http://stackoverflow.com/questions/2590495/problem-when-mixing-type-classes-and-type-families?rq=1 –
Could zastosowali nowy typ zamiast danych - nie? – lynnard