Skip to content

Add decideSymbol, decideNat, decideChar, decTypeRep and decT #98

@phadej

Description

@phadej
-- sameSymbol returns Maybe (a :~: b)
decideSymbol :: (KnownSymbol a, KnownSymbol b) =>
              proxy1 a -> proxy2 b -> Either (a :~: b -> Void) (a :~: b)
decideSymbol x y
  | symbolVal x == symbolVal y  = Right (unsafeCoerce Refl)
  | otherwise                   = Left (\Refl -> errorWithoutStackTrace ("decideSymbol: A proof of " ++ show (symbolVal x) ++ " :~: " ++ show (symbolVal y)))
  
-- decideNat and decideChar similarly for Natural and Char.
-- the eqTypeRep returns Maybe (a :~: b)
decTypeRep :: forall k1 k2 (a :: k1) (b :: k2).
             TypeRep a -> TypeRep b -> Either (a :~~: b -> Void) (a :~~: b)
decTypeRep a b
  | sameTypeRep a b = Right (unsafeCoerce HRefl)
  | otherwise       = Left (\HRefl -> errorWithoutStackTrace ("decTypeRep: got a proof of " ++ show a ++ " :~~: " ++ show b))
  
-- | eqT returns Maybe (a :~: b)
decT :: forall a b. (Typeable a, Typeable b) => Either (a :~: b -> Void) (a :~: b)
decT = ...

The sameSymbol, sameNat, sameChar and eqTypeRep could be safely† re-implemented using these new combinators:

sameSymbol a b = either (const Nothing) Maybe (decSymbol a b)

but it's probably better to not change their implementations, as they are quite simple anyway.

† by safely I mean without relying on any internal implementation details. Thus if we had decide variants from the beginning, libraries could have defined Maybe (a :~: b) variants if they needed them, but defining decide variants using same functions is relying on (undocumented!) implementation details.


This unsafe code already exists in singletons-base, and I argue that such unsafe stuff is better to define next to the actual types.

https://hackage.haskell.org/package/singletons-base-3.1.1/docs/src/GHC.TypeLits.Singletons.Internal.html#line-111

instance SDecide Symbol where
  (SSym :: Sing n) %~ (SSym :: Sing m)
    | Just r <- sameSymbol (Proxy :: Proxy n) (Proxy :: Proxy m)
    = Proved r
    | otherwise
    = Disproved (\Refl -> error errStr)
    where errStr = "Broken Symbol singletons"

and https://hackage.haskell.org/package/singletons-base-3.1.1/docs/src/Data.Singletons.Base.TypeRepTYPE.html#line-93

instance SDecide (TYPE rep) where
  tra %~ trb =
    case eqTypeRep tra trb of
      Just HRefl -> Proved Refl
      Nothing    -> Disproved (\Refl -> error "Type.Reflection.eqTypeRep failed")

cc @RyanGlScott

Metadata

Metadata

Assignees

No one assigned

    Labels

    approvedApproved by CLC votebase-4.19Implemented in base-4.19 (GHC 9.8)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions