While implementing a refinement type system, I need to put in checks to make sure the types are well-formed. For example, a type like Num[100,0]
shouldn't happen, where Num[lb,ub]
is the type of numbers larger than lb
and smaller than ub
. I then wrote:
-- FORMATION RULES
class RefTy t
where tyOK :: t -> Bool
instance RefTy Ty
where tyOK (NumTy (n1, n2)) = n1 <= n2
tyOK (CatTy cs) = isSet cs
{-
data WellFormed t = Valid t
| Invalid
instance Monad WellFormed
where
(>>=) :: RefTy a => WellFormed a -> (a -> WellFormed b) -> WellFormed b
Valid t >>= f
| tyOK t = f t
| otherwise = Invalid
Invalid >>= _ = Invalid
-}
Which got me into the known problem of "restricted Monad". The suggested answer is to have the Wellformed
monad to be general but restrict the functions. However that would go back to adding the well-formed check everywhere. Is there a better way to get around?