Reputation: 6856
Consider the following typeclass that defines pairs of types:
class Constraint a b where
g :: a -> b
For all instances of constraint we can derive a set of types a
, essentially an implicit typeclass, let's call it A
. For each instance of typeclass A
there is another implicit typeclass B
which is includes all possible types b
for Constraint A b
.
So here is a piece of code.
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Debug.Trace
-- Contraining class
class (Show a, Show b) => QandA a b where
g :: a -> b
-- Some data types
data A = A1 | A2 deriving (Show, Eq)
data B = B1 | B2 deriving (Show, Eq)
data C = C1 | C2 deriving (Show, Eq)
instance QandA A B where
g A1 = B1
g A2 = B2
instance QandA A C where
g A1 = C1
g A2 = C2
-- We want to define a set of types that includes all the types that
-- have Constraint a b given a. This can be done via an intermediate
-- type.
data DefaultAnswer q = forall a . (DefaultingQuestion q, QandA q a) => DefaultAnswer {answer :: a};
-- Polymorphism
class DefaultingQuestion q where
def :: DefaultAnswer q
instance DefaultingQuestion A where
def = DefaultAnswer C1
Which typechecks but in ghci
> (def :: DefaultAnswer A)
(def :: DefaultAnswer A) :: DefaultAnswer A
But
> answer (def :: DefaultAnswer A)
<interactive>:574:1:
Cannot use record selector "answer" as a function due to escaped type variables
Probable fix: use pattern-matching syntax instead
In the expression: answer (def :: DefaultAnswer A)
In an equation for "it": it = answer (def :: DefaultAnswer A)
Now the way I understand it is that, since I use existential types, GHC does not really look for the type of answer
, it just makes sure there could be one even if it has no way of figuring out which one it is. So then when I actually want to run answer
it can't figure out how to deal with it.
So my question is: is there a way to define a default answer for each type that implements DefaultingQuestion
Upvotes: 0
Views: 151
Reputation: 38893
Why not:
import Data.Proxy
class DefaultingQuestion q a where
def :: Proxy q -> a
instance DefaultingQuestion A where
def _ = C1
Upvotes: 1