The problem is that it seems to you that you need two conflicting points at once:
- You need different names for the same type
- You want the compiler to understand these two types of names as belonging to different types
Based on the domain, I think that you certainly do not want to use type synonyms and that you need the actual new types (with the accompanying type constructors). If AndClause is a synonym for [Literal] , and OrClause is a synonym for [Literal] , by the transitive property, AndClause and OrClause are mutually synonymous. Therefore, the compiler has no reason to distinguish between them (thus, there can be no polymorphism).
What you really want are two different types that behave differently, for which newtype will only do fine:
newtype AndClause = AndClause [Literal] newtype OrClause = OrClause [Literal] instance Satisfiable AndClause where satisfy (AndClause l:ls) = --... instance Satisfiable OrClause where satisfy (OrClause l:ls) = --...
But, an even better idea might be to make it an algebraic data type:
data Prop = And [Literal] | Or [Literal] instance Satisfiable Prop where satisfy (And l:ls) = --... satisfy (Or l:ls) = --...
(Note that I am printing this from the compiler, but in principle this should be correct).
source share