[Haskell-cafe] Composing analyses.

Serguey Zefirov sergueyz at gmail.com
Wed Jan 4 20:44:59 CET 2012

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?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: a.hs
Type: application/octet-stream
Size: 2434 bytes
Desc: not available
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120104/ddb5c092/attachment.obj>

More information about the Haskell-Cafe mailing list