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?

Attachment: a.hs
Description: Binary data

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to