- insert alist@(cur_item@(cur_tys, _) : rest)
- | unifiable && not overlap_ok = failMaB cur_item
- | unifiable && ins_item_more_specific = returnMaB (ins_item : alist)
- | unifiable && not cur_item_more_specific = failMaB cur_item
- | otherwise = -- Less specific, or not unifiable... carry on
- insert rest `thenMaB` \ rest' ->
- returnMaB (cur_item : rest')
+ insert alist@(cur_item@(tpl_tvs, tpl_tys, val) : rest)
+
+ -- FAIL if:
+ -- (a) they are the same, or
+ -- (b) they unify, and any sort of overlap is prohibited,
+ -- (c) they unify but neither is more specific than t'other
+ | identical
+ || (unifiable && not overlap_ok)
+ || (unifiable && not (ins_item_more_specific || cur_item_more_specific))
+ = failMaB (tpl_tys, val)
+
+ -- New item is an instance of current item, so drop it here
+ | ins_item_more_specific = returnMaB (ins_item : alist)
+
+ -- Otherwise carry on
+ | otherwise = insert rest `thenMaB` \ rest' ->
+ returnMaB (cur_item : rest')