goldfirere / singletons

Fake dependent types in Haskell using singletons

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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!