Add helper for hand-written SDecide instances?
shlevy opened this issue · comments
I just found myself reaching for this in defining a simple SDecide
instance:
type RefuteHelper :: forall k1 k2 . k1 -> k2 -> Type
type family RefuteHelper x y where
RefuteHelper a a = ()
RefuteHelper _ _ = Void
refuted :: Sing a -> Sing b -> a :~: b -> RefuteHelper a b
refuted a _ Refl = ()
Would this, or some appropriately more general version, be useful upstream in Data.Singletons.Decide
?
Can you elaborate on how you're using RefuteHelper
to define an SDecide
instance? It's not obvious to me what the connection is.
instance SingKind Longevity where
type Demote Longevity = Longevity
fromSing SShort = Short
fromSing SLong = Long
toSing Short = SomeSing SShort
toSing Long = SomeSing SLong
instance SDecide Longevity where
SShort %~ SShort = Proved Refl
SLong %~ SLong = Proved Refl
SShort %~ SLong = Disproved (refuted SShort SLong)
SLong %~ SShort = Disproved (refuted SLong SShort)
Perhaps this approach is not Haskelly enough, it's the closest analogue to what I'd write in Agda/coq
The way that singletons-th
would generate an SDecide
instance for that data type would be by using EmptyCase
, i.e.,
instance SDecide Longevity where
SShort %~ SShort = Proved Refl
SLong %~ SLong = Proved Refl
SShort %~ SLong = Disproved (\p -> case p of {})
SLong %~ SShort = Disproved (\p -> case p of {})
This is shorter (and could be made even shorter with LambdaCase
), but more importantly, it works without needing any auxiliary definitions. I wonder if this would work for your use case? I'm inclined to just recommend that instead.
Ah, this works, thanks!