To create a type class that accepts the type-level naturals Z, (S Z), (S (S Z))... etc, you can simply declare the instances recursively as such:
data Z
data S a
class Type a
instance Type Z
instance Type (S a)
Is it possible to create a type class instance based on type level predicates? For example, I want to be able to say:
{-# LANGUAGE MultiParamTypeClasses #-}
class Type a b
instance Type x y when (x :+: y == 8)
Where :+: is type level addition, and == is type-level equality from Data.Type.Equality, so that instances are only created for pairs of nats that add up to 8.
Is notation similar to this available in Haskell? If not, how would something like this be accomplished?
Edit: This post was inspired by the Haskell wiki article on smart constructors, where a type class InBounds was declared to statically verify that the phantom type argument passed to a smart constructor was in some range of Nats, the smart constructor was:
resistor :: InBounds size => size -> Resistor size
resistor _ = Resistor
Trying to do something similar in my example (after using leftaroundabout's answer) gives me an error:
construct :: (Type a b) => a -> b -> MyType a b
construct _ _ = MyType
>>> Expected a type, but a has kind Nat…
The example from the Haskell wiki works because it doesn't use DataKinds, is it possible to pass a type of kind Nat to a value-level function?