How to put constraints on type variable of kind `Constraint`?

前端 未结 3 2271
北海茫月
北海茫月 2021-02-19 05:07

I\'m playing around with the ConstraintKinds extension of GHC. I have the following data type, which is just a box for things fulfilling some one parameter constrai

3条回答
  •  旧巷少年郎
    2021-02-19 06:02

    You cannot make Some c an instance of Show, except trivially.

    You want to show the a inside Some, but that variable is existentially quantified, so we cannot depend on any knowledge of the type of a. In particular, we have no way of knowing that a is an instance of Show.

    EDIT: I'll expand on my answer. Even with more machinery, and giving up on a Show instance, I still don't think what you want is possible because of the existential quantification.

    First I'll rewrite Some in a more familiar form

    data Dict p where
        Dict :: p a => a -> Dict p
    

    The usual way to talk about "constraints implying constraints" is with the concept of constraint entailment.

    data p :- q where
        Sub :: p a => Dict q -> p :- q
    

    We can think about a value of type p :- q as a proof that if the constraint forall a. p a holds, then forall a. q a follows.

    Now we try to write a sensible show-ish function

    showD :: p :- Show -> Dict p -> String
    showD (Sub (Dict a)) (Dict b) = show b
    

    At a glance, this might work. We have brought the following constraints into scope (forgive the pseudo-exists syntax)

    (0) p :: * -> Constraint
    (1) exists a. p a           -- (Dict p)
    (2) exists b. p b => Show b -- (p :- Show)
    

    But now things fall apart, GHC rightfully complains:

    main.hs:10:33:
        Could not deduce (Show a2) arising from a use of `show' 
        from the context (p a)
          bound by a pattern with constructor
                     Sub :: forall (p :: * -> Constraint) (q :: * -> Constraint) a.
                            (p a) => 
                            Dict q -> p :- q,
                   in an equation for `showD' 
          at main.hs:10:8-19                    
        or from (Show a1) 
          bound by a pattern with constructor
                     Dict :: forall (p :: * -> Constraint) a. (p a) => a -> Dict p, 
                   in an equation for `showD'
          at main.hs:10:13-18 
        or from (p a2)
          bound by a pattern with constructor
                     Dict :: forall (p :: * -> Constraint) a. (p a) => a -> Dict p,
                   in an equation for `showD'
          at main.hs:10:23-28   
    

    because it is impossible to unify the a from (1) with the b from (2).

    This is the same essential idea that is used throughout the constraints package mentioned in the comments.

提交回复
热议问题