How can I encode a constraint implication in Haskell into a new constraint? In my example, I want to require that every Functor c d f
needs to be such that Obj c x
implies Obj c (f x)
. I am writing the constraint forall x . Obj c x => Obj d (f x)
.
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE QuantifiedConstraints #-}
import Prelude hiding (id, Functor, fmap)
import Data.Kind
class Category c where
type Obj c a :: Constraint
id :: (Obj c x) => c x x
comp :: (Obj c x) => c y z -> c x y -> c x z
class ( Category c, Category d, forall x . Obj c x => Obj d (f x))
=> Functor c d f where
fmap :: (Obj c x, Obj c y) => c x y -> d (f x) (f y)
doublefmap :: forall c f x . (Category c , Functor c c f, Obj c x)
=> c x x -> c (f (f x)) (f (f x))
doublefmap = fmap @c @c @f . fmap @c @c @f
But this produces the following error:
Minimal.hs:27:14: error:
• Could not deduce: Obj c (f x) arising from a use of ‘fmap’
from the context: (Functor c c f, Obj c x)
bound by the type signature for:
doublefmap :: forall (c :: * -> * -> *) (f :: * -> *) x.
(Category c, Functor c c f, Obj c x) =>
c x x -> c (f (f x)) (f (f x))
at Minimal.hs:(25,1)-(26,44)
• In the first argument of ‘(.)’, namely ‘fmap @c @c @f’
In the expression: fmap @c @c @f . fmap @c @c @f
In an equation for ‘doublefmap’:
doublefmap = fmap @c @c @f . fmap @c @c @f
• Relevant bindings include
doublefmap :: c x x -> c (f (f x)) (f (f x))
(bound at Minimal.hs:27:1)
What am I doing wrong here? What additional hints should I give the compiler? Is there any better way of achieving this?
My guess is that I would need to use Data.Constraint
and :-
, but how?
This is a second solution without using
Data.Constraint
that (at least to me) seems a bit more elegant.I would be happy if someone can improve this.