You can not have anything like
data Sub = SubA | SubB
data Super = Sub | SuperB
Suppose the above syntax is allowed, then the problem is given the value constructor SubA
you can not tell whether its type is Sub
or Super
. That's why you need to wrap your type in a constructor.
For your second example, the way you are doing should be the default way of doing but you can do a hack to make it easier although I don't recommend doing this as using show is much slower. You can try some other hack similar to this.
import Data.List
data Super = SubA | SubB | SuperB deriving Show
isSub :: Super -> Bool
isSub m = isPrefixOf "Sub" (show m)
If you really want to have something like above it is better to define function like you did. Using TH might save you sometime.
Your third case is what I would really recommend doing. You need to have a wrapper constructor like SuperA
because of the reasons I told above. That's why you can't have exactly type1 is of type2 plus x,y,z. The closest thing you can have is to wrap elements in a constructor or using a typeclass.
data Sub = SubA | SubB
data Sup = SuperA | SuperB
class Super a where
isSub :: a -> Bool
isSub _ = True
instance Super Sup where
isSub _ = False
instance Super Sub
data SupSup = SuperSuperA | SuperSuperB
class SuperSuper a where
isSuper :: a -> Bool
isSuper _ = True
instance SuperSuper SupSup where
isSuper _ = False
instance SuperSuper Sup
instance SuperSuper Sub
You can think here Super
(which is a typeclass and not a type) contains Sub
and someting extra (Sup
).