Тут у меня код получился, который должен работать, но не работает.
{-# LANGUAGE GADTs, TypeFamilies, MultiParamTypeClasses, TypeOperators #-}
{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances, EmptyDataDecls #-}
import Control.Monad
import Control.Monad.State
-------------------------------------------------------------------------------
-- Home brewn HList.
data Nil
infixr 5 :.
data a :. b
class FAIL a -- no instances!
-------------------------------------------------------------------------------
-- Monad.
type M as a = StateT as IO a
getAnalysisResult :: EnabledAnalysis a as => a -> M as Int
getAnalysisResult _ = error "getAnalysisResult!!!"
setAnalysisResult :: EnabledAnalysis a as => a -> Int -> M as ()
setAnalysisResult _ _ = error "setAnalysisResult!!!"
-------------------------------------------------------------------------------
-- Analysis classes.
-- |Analysis called for
class (Analyses (RequiresAnalyses a)) => Analysis a where
-- |What has to be done before our pass.
type RequiresAnalyses a
-- |Perform an analysis.
perform :: (EnabledAnalysis a as, EnabledAnalyses (RequiresAnalyses a) as) =>
a -> M as ()
-- |HList of analyses.
class Analyses as where
instance Analyses Nil where
instance (Analysis a, Analyses as) => Analyses (a :. as) where
data AnalysisNotEnabled a
class EnabledAnalysis a as
instance (FAIL (AnalysisNotEnabled a)) => EnabledAnalysis a Nil
instance (Analysis a, Analyses as) => EnabledAnalysis a (a :. as)
instance (Analysis a, Analysis a', EnabledAnalysis a as) => EnabledAnalysis a (a' :. as)
class EnabledAnalyses as eas
instance EnabledAnalyses Nil eas
instance (EnabledAnalyses as eas, EnabledAnalysis a eas) => EnabledAnalyses (a :. as) eas
-------------------------------------------------------------------------------
-- Analysis instances.
data Base = Base
instance Analysis Base where
type RequiresAnalyses Base = Nil
perform a = do
x <- getAnalysisResult a
setAnalysisResult a (x+1)
data Derived = Derived
instance Analysis Derived where
type RequiresAnalyses Derived = Base :. Nil
perform a = do
x <- getAnalysisResult a
y <- getAnalysisResult Base
setAnalysisResult a (x+y)
По идее, контекст (EnabledAnalysis a as, EnabledAnalyses (RequiresAnalyses a) as) функции perform должен раскрываться, но не раскрывается.
В результате получается
ошибка:
Prelude> :r
[1 of 1] Compiling Main ( a.hs, interpreted )
a.hs:78:22:
Could not deduce (EnabledAnalysis Base as)
arising from a use of `getAnalysisResult'
from the context (EnabledAnalysis Derived as,
EnabledAnalyses (RequiresAnalyses Derived) as)
bound by the type signature for
perform :: (EnabledAnalysis Derived as,
EnabledAnalyses (RequiresAnalyses Derived) as) =>
Derived -> M as ()
at a.hs:(76,9)-(79,41)
Possible fix:
add (EnabledAnalysis Base as) to the context of
the type signature for
perform :: (EnabledAnalysis Derived as,
EnabledAnalyses (RequiresAnalyses Derived) as) =>
Derived -> M as ()
or add an instance declaration for (EnabledAnalysis Base as)
In a stmt of a 'do' expression: y <- getAnalysisResult Base
In the expression:
do { x <- getAnalysisResult a;
y <- getAnalysisResult Base;
setAnalysisResult a (x + y) }
In an equation for `perform':
perform a
= do { x <- getAnalysisResult a;
y <- getAnalysisResult Base;
setAnalysisResult a (x + y) }
Failed, modules loaded: none.
Ошибка получается с ghc 6.12.1, 7.0.4. Если у кого есть 7.2 или 7.4 - попробуйте, пожалуйста. Вдруг у вас ошибки не будет.