Search code examples
haskelltypeclassghci

How to check from the REPL that a given constraint is satisfied?


For the sake of exploring libraries with complex types and typeclass instances, I want to check from the REPL whether a typeclass constraint is satisfied or not (provided all the relevant dataypes and instances are in scope).

For example: in rel8 1.5.0, is the constraint Table Expr (Expr Int, Expr Bool) satisfied? (It's not, as Int lacks a DBType instance, so the preconditions fail).

Non-solutions:

  • Using :kind!. This only checks that the constraint is well-formed, not that it's satisified.

    ghci> :kind! (Table Expr (Expr Int, Expr Bool))
    (Table Expr (Expr Int, Expr Bool)) :: Constraint
    = Table Expr (Expr Int, Expr Bool)
    
  • Using :instances. Doesn't seem to work with multi-parameter typeclasses like Table, and moreover it returns all possible instances, which can be verbose.

    ghci> :instances Expr
    instance Reifiable Expr
    instance Nullifiable Expr
    instance GRecordable Expr
    
    ghci> :instances (Expr Int, Expr Bool)
    instance [safe] NotNull (Expr Int, Expr Bool)
    instance [safe] Nullable (Expr Int, Expr Bool)
    instance Show (Expr Int, Expr Bool) 
    instance GHC.Generics.Generic (Expr Int, Expr Bool)
    

Solution

  • I have defined the following function in my .ghci file:

    :set -XAllowAmbiguousTypes
    :{
    yep :: forall c . c => ()
    yep = ()
    :}
    

    Which can be used like this

    ghci> yep @(Table Expr (Expr Int, Expr Bool))
    <interactive>:4:1: error: [GHC-39999]
        • No instance for ‘DBType Int’ arising from a use of ‘yep’
        • In the expression: yep @(Table Expr (Expr Int, Expr Bool))
          In an equation for ‘it’:
              it = yep @(Table Expr (Expr Int, Expr Bool))
    
    ghci> yep @(Table Expr (Expr Int32, Expr Bool))
    ()