Require a constraint for every element of a list.
If you have a datatype that is indexed over a type-level list, then you can use All to indicate that all elements of that type-level list must satisfy a given constraint.
Example: The constraint
All Eq '[ Int, Bool, Char ]is equivalent to the constraint
(Eq Int, Eq Bool, Eq Char)Example: A type signature such as
f :: All Eq xs => NP I xs -> ...means that f can assume that all elements of the n-ary
product satisfy Eq.
Note on superclasses: ghc cannot deduce superclasses from All constraints. You might expect the following to compile
class (Eq a) => MyClass a
foo :: (All Eq xs) => NP f xs -> z
foo = [..]
bar :: (All MyClass xs) => NP f xs -> x
bar = foobut it will fail with an error saying that it was unable to
deduce the class constraint AllF Eq xs (or similar) in the
definition of bar.
In cases like this you can use Dict from Data.SOP.Dict
to prove conversions between constraints.
See this answer on SO for more details.
Methods
cpara_SList :: proxy c -> r '[] -> (forall (y :: k) (ys :: [k]). (c y, All c ys) => r ys -> r (y ': ys)) -> r xsConstrained paramorphism for a type-level list.
The advantage of writing functions in terms of cpara_SList is that they are then typically not recursive, and can be unfolded statically if the type-level list is statically known.