{-# OPTIONS_GHC -fno-warn-redundant-constraints #-} {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, FlexibleContexts #-} -- Compiles fine. -- Instance selection works fine. -- try: :t foo (T1b T1a) module ShouldCompile where -- Notice: T1 is a recursive type. -- Notice: the classes are recursive, too. -- Why does this work when almost the same thing doesn't? -- Say: adding an Int component to T1a makes things loop. -- See LoopOfTheDay2.hs and LoopOfTheDay3.hs. data T1 = T1a | T1b T1 class C0 x where foo :: x -> (); foo = undefined class C1 x y class C1 x y => C2 x y instance C0 T1 => C1 () T1 -- (I1) instance (C1 x T1) => C2 x T1 -- (I2) instance C2 () T1 => C0 T1 -- (I3) baz = foo (T1b T1a) {- Need C0 T1 -->(I3) C2 () T1 -->(I2) C1 () T1 -->(I1) C0 T1 -- STOP because we've seen this before -}