Well, the simple answer is to drop arity from a smart constructor.
makePred :: Name -> Arguments -> Predicate makePred name args = Pred name (length args) args
Then, if you do not expose the Pred constructor from your module and force your clients to go through makePred , you know that they will always match, and you wonβt need this unsightly Maybe .
There is no direct way to enforce this invariant. That is, you cannot get makePred 2 ["a","b"] to typecheck, but makePred 2 ["a","b","c"] not to. To do this, you need real dependent types.
There are places in the middle to convince haskell to force your invariants to be used using advanced functions ( GADT + phantom types), but after drinking the whole solution, I realized that I really did not consider your question, and that such methods didnβt really applicable to this problem. Usually this is more of a problem than in general. I would stick with a smart constructor.
I wrote a detailed description of the idea of ββan intelligent designer . It turns out to be a pretty nice environment between type checking and runtime checking.
luqui
source share