So, I found out that the type level machinery to get restricted type arguments is surprinsingly small nowadays :
testA :: OneOf '[Text] Text
testA = "ok"
-- Type error :
-- • The provided type
-- Int
-- does not match any of the type in the provided OneOf list
-- '[Text]
-- • In the expression: 10
-- In an equation for ‘testB’: testB = 10
testB :: OneOf '[Text] Int
testB = 10
-- Type error :
-- • You provided an empty type list for your OneOf, so nothing will typecheck, your type is equivalent to Void
-- • In the expression: "qsd"
-- In an equation for ‘testC’: testC = "qsd"
testC :: OneOf '[] Int
testC = "qsd"
type OneOf listOfType target = OneOfAccum '[] listOfType target
type family OneOfAccum consumed listOfType target where
OneOfAccum '[] '[] target = TypeError ('Text "You provided an empty type list for your OneOf, so nothing will typecheck, your type is equivalent to Void")
OneOfAccum _ (target : resOfType) target = target
OneOfAccum currentAcc (v : resOfType) target = OneOfAccum (v : currentAcc) resOfType target
OneOfAccum allCons '[] target = TypeError ('Text "The provided type "
':$$: 'ShowType target ':$$: 'Text " does not match any of the type in the provided OneOf type list " ':$$: 'ShowType allCons)
I find this quite nice. Of course it’s not perfect, since the type error only comes out when it typechecks and not in type aliases or type signatures for instance but still, it seems good.
Hence my question, why don’t people use more this feature, and is there anything in base (or a widespread library) similar to this OneOf type family ?