问题
Still playing with existentials over constraints (just exploring this design space, I know it is considered bad by many Haskellers). See this question for more info.
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ConstraintKinds #-}
{-# Language TypeApplications #-}
import GHC.Exts (Constraint)
class Foo a where
foo :: a -> Int
class Foo a => Bar a where
bar :: a -> String
instance Foo Int where
foo = id
instance Bar Int where
bar = show
data Obj cls = forall o. (cls o) => Obj o
fooable = Obj @Foo $ (42 :: Int)
barable = Obj @Bar $ (42 :: Int)
doFoo :: Obj Foo -> Int
doFoo (Obj x) = foo x
Now I have this problem. doFoo fooable
works, but doFoo barable
doesn't.
• Couldn't match type ‘Bar’ with ‘Foo’
Expected type: Obj Foo
Actual type: Obj Bar
• In the first argument of ‘doFoo’, namely ‘barable’
In the expression: doFoo barable
In an equation for ‘it’: it = doFoo barable
Which is of course true. Obj Foo
is different for Obj Bar
.
Can I give a suitable type to doFoo
? Basically I want a type like Obj cls where cls is a subclass of Foo
but I cannot find a way to express it. Please bear with me, I'm new to these wild wonderful types.
回答1:
You can use a quantified constraint for that:
{-# LANGUAGE QuantifiedConstraints #-}
doFoo :: forall c . (forall a. c a => Foo a) => Obj c -> Int
doFoo (Obj x) = foo x
Essentially, doFoo
takes any Obj c
, where c
is any type class which implies Foo
, i.e. a type class satisfying the quantified constraint
forall a. c a => Foo a
来源:https://stackoverflow.com/questions/62673111/can-i-express-a-subclassing-constraint