X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdocs%2Fusers_guide%2Fglasgow_exts.xml;h=a5ac2b3b9784bcfd64cef599324e65690ced9ebb;hb=59c9c122f942f348008d4ed8ba088286343d63d3;hp=620f8b68ecc27f35ba7cf96ffa9fd4ba5edf7223;hpb=8b3ccdc9c224207df38821681c46cfd73d81081b;p=ghc-hetmet.git diff --git a/ghc/docs/users_guide/glasgow_exts.xml b/ghc/docs/users_guide/glasgow_exts.xml index 620f8b6..a5ac2b3 100644 --- a/ghc/docs/users_guide/glasgow_exts.xml +++ b/ghc/docs/users_guide/glasgow_exts.xml @@ -1673,38 +1673,124 @@ class like this: Instance declarations - -Instance heads + +Relaxed rules for instance declarations + +An instance declaration has the form + + instance ( assertion1, ..., assertionn) => class type1 ... typem where ... + +The part before the "=>" is the +context, while the part after the +"=>" is the head of the instance declaration. + -The head of an instance declaration is the part to the -right of the "=>". In Haskell 98 the head of an instance -declaration +In Haskell 98 the head of an instance declaration must be of the form C (T a1 ... an), where C is the class, T is a type constructor, and the a1 ... an are distinct type variables. +Furthermore, the assertions in the context of the instance declaration be of +the form C a where a is a type variable. -The flag lifts this restriction and allows the -instance head to be of form C t1 ... tn where t1 -... tn are arbitrary types (provided, of course, everything is -well-kinded). In particular, types ti can be type variables -or structured types, and can contain repeated occurrences of a single type -variable. -Examples: +The flag loosens these restrictions +considerably. Firstly, multi-parameter type classes are permitted. Secondly, +the context and head of the instance declaration can each consist of arbitrary +(well-kinded) assertions (C t1 ... tn) subject only to the following rule: +for each assertion in the context + +No type variable has more occurrences in the assertion than in the head +Tthe assertion has fewer constructors and variables (taken together + and counting repetitions) than the head + +These restrictions ensure that context reduction terminates: each reduction +step makes the problem smaller +constructor. For example, the following would make the type checker +loop if it wasn't excluded: + + instance C a => C a where ... + +For example, these are OK: - instance Eq (T a a) where ... - -- Repeated type variable + instance C Int [a] -- Multiple parameters + instance Eq (S [a]) -- Structured type in head - instance Eq (S [a]) where ... - -- Structured type + -- Repeated type variable in head + instance C4 a a => C4 [a] [a] + instance Stateful (ST s) (MutVar s) - instance C Int [a] where ... - -- Multiple parameters + -- Head can consist of type variables only + instance C a + instance (Eq a, Show b) => C2 a b + + -- Non-type variables in context + instance Show (s a) => Show (Sized s a) + instance C2 Int a => C3 Bool [a] + instance C2 Int a => C3 [a] b + +But these are not: + + instance C a => C a where ... + -- Context assertion no smaller than head + instance C b b => Foo [b] where ... + -- (C b b) has more more occurrences of b than the head + + +A couple of useful idioms are these. First, +if one allows overlapping instance declarations then it's quite +convenient to have a "default instance" declaration that applies if +something more specific does not: + + instance C a where + op = ... -- Default + + +Second, sometimes you might want to use the following to get the +effect of a "class synonym": + + + + class (C1 a, C2 a, C3 a) => C a where { } + + instance (C1 a, C2 a, C3 a) => C a where { } + +This allows you to write shorter signatures: + + + f :: C a => ... + +instead of + + f :: (C1 a, C2 a, C3 a) => ... + + + + + +Undecidable instances + + +Sometimes even the rules of are too onerous. +Voluminous correspondence on the Haskell mailing list has convinced me +that it's worth experimenting with more liberal rules. If you use +the experimental flag +-fallow-undecidable-instances +option, you can use arbitrary +types in both an instance context and instance head. Termination is ensured by having a +fixed-depth recursion stack. If you exceed the stack depth you get a +sort of backtrace, and the opportunity to increase the stack depth +with N. + + +I'm on the lookout for a less brutal solution: a simple rule that preserves decidability while +allowing these idioms interesting idioms. + + Overlapping instances @@ -1835,112 +1921,6 @@ reversed, but it makes sense to me. - -Undecidable instances - -An instance declaration must normally obey the following rules: - -At least one of the types in the head of -an instance declaration must not be a type variable. -For example, these are OK: - - - instance C Int a where ... - - instance D (Int, Int) where ... - - instance E [[a]] where ... - -but this is not: - - instance F a where ... - -Note that instance heads may contain repeated type variables (). -For example, this is OK: - - instance Stateful (ST s) (MutVar s) where ... - - - - - - -All of the types in the context of -an instance declaration must be type variables. -Thus - -instance C a b => Eq (a,b) where ... - -is OK, but - -instance C Int b => Foo b where ... - -is not OK. - - - -These restrictions ensure that -context reduction terminates: each reduction step removes one type -constructor. For example, the following would make the type checker -loop if it wasn't excluded: - - instance C a => C a where ... - -There are two situations in which the rule is a bit of a pain. First, -if one allows overlapping instance declarations then it's quite -convenient to have a "default instance" declaration that applies if -something more specific does not: - - - - instance C a where - op = ... -- Default - - - -Second, sometimes you might want to use the following to get the -effect of a "class synonym": - - - - class (C1 a, C2 a, C3 a) => C a where { } - - instance (C1 a, C2 a, C3 a) => C a where { } - - - -This allows you to write shorter signatures: - - - - f :: C a => ... - - - -instead of - - - - f :: (C1 a, C2 a, C3 a) => ... - - - -Voluminous correspondence on the Haskell mailing list has convinced me -that it's worth experimenting with more liberal rules. If you use -the experimental flag --fallow-undecidable-instances -option, you can use arbitrary -types in both an instance context and instance head. Termination is ensured by having a -fixed-depth recursion stack. If you exceed the stack depth you get a -sort of backtrace, and the opportunity to increase the stack depth -with N. - - -I'm on the lookout for a less brutal solution: a simple rule that preserves decidability while -allowing these idioms interesting idioms. - - - @@ -4902,7 +4882,7 @@ key_function :: Int -> String -> (Bool, Double) for the original function, not its code): f :: Eq a => a -> b -> b - {-# SPECIALISE g :: Int -> b -> b #-} + {-# SPECIALISE f :: Int -> b -> b #-} g :: (Eq a, Ix b) => a -> b -> b {-# SPECIALISE g :: (Eq a) => a -> Int -> Int #-} @@ -4915,6 +4895,35 @@ RULE with a somewhat-complex left-hand side (try it yourself), so it might not f well. If you use this kind of specialisation, let us know how well it works. +A SPECIALIZE pragma can optionally be followed with a +INLINE or NOINLINE pragma, optionally +followed by a phase, as described in . +The INLINE pragma affects the specialised verison of the +function (only), and applies even if the function is recursive. The motivating +example is this: + +-- A GADT for arrays with type-indexed representation +data Arr e where + ArrInt :: !Int -> ByteArray# -> Arr Int + ArrPair :: !Int -> Arr e1 -> Arr e2 -> Arr (e1, e2) + +(!:) :: Arr e -> Int -> e +{-# SPECIALISE INLINE (!:) :: Arr Int -> Int -> Int #-} +{-# SPECIALISE INLINE (!:) :: Arr (a, b) -> Int -> (a, b) #-} +(ArrInt _ ba) !: (I# i) = I# (indexIntArray# ba i) +(ArrPair _ a1 a2) !: i = (a1 !: i, a2 !: i) + +Here, (!:) is a recursive function that indexes arrays +of type Arr e. Consider a call to (!:) +at type (Int,Int). The second specialisation will fire, and +the specialised function will be inlined. It has two calls to +(!:), +both at type Int. Both these calls fire the first +specialisation, whose body is also inlined. The result is a type-based +unrolling of the indexing function. +Warning: you can make GHC diverge by using SPECIALISE INLINE +on an ordinarily-recursive function. + Note: In earlier versions of GHC, it was possible to provide your own specialised function for a given type: