
I am trying to create a stack of analyses. There are basic analyses then there are derived analyses that create a DAG of analyses. I thought I can express their relationship through type classes, but I failed. I've attached the source of my failure. Main points are below: getAnalysisResult :: EnabledAnalysis a as => a -> M as Int getAnalysisResult _ = error "getAnalysisResult!!!" setAnalysisResult :: EnabledAnalysis a as => a -> Int -> M as () setAnalysisResult _ _ = error "setAnalysisResult!!!" -- |Analysis interface. What to require and what to perform. 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 () data AnalysisNotEnabled a -- |Check if analysis is enabled. 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) -- |Check if a group of analyses is enabled. class EnabledAnalyses as eas instance EnabledAnalyses Nil eas instance (EnabledAnalyses as eas, EnabledAnalysis a eas) => EnabledAnalyses (a :. as) eas -- Base analysis. data Base = Base instance Analysis Base where type RequiresAnalyses Base = Nil perform a = do x <- getAnalysisResult a setAnalysisResult a (x+1) -- And analysis derived from Base. data Derived = Derived instance Analysis Derived where type RequiresAnalyses Derived = Base :. Nil -- !!! this is the source of problems -- the type here is -- (EnabledAnalysis Derived as, EnabledAnalyses (Base :. Nil) as) => -- Derived -> M as () -- Looks like ghc does not expand RequiresAnalyses Derived. perform a = do x <- getAnalysisResult a y <- getAnalysisResult Base setAnalysisResult a (x+y) -- here I expanded RequiresAnalysis Derived manually. -- ghc thinks that "EnabledAnalyses (Base :. Nil) as" does not imply "EnableAnalysis Base as". -- it is weird. performDerived :: (EnabledAnalysis Derived as, EnabledAnalyses (Base :. Nil) as) => Derived -> M as () performDerived a = do x <- getAnalysisResult a y <- getAnalysisResult Base setAnalysisResult a (x+y) This is behavior of ghc 6.12.1, 7.0.4 and 7.2.1. Is it right behavior? The main question is: is it possible to combine computations like this? How should one do this? I thinking about abandoning type classes altogether. I think I can do it some other way. But out of curiosity - why is that?
participants (1)
-
Serguey Zefirov