I would like to test if all fields in a record have the same specified constructor. ext1Q works for Maybe type but not Either type. Why is that?
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Maybe (isNothing, isJust)
import Data.Either (isLeft, isRight)
import Data.Data (Data, gmapQ)
import Data.Generics.Aliases (ext1Q)
allNothing :: (Data d) => d -> Bool
allNothing = and . gmapQ (const True `ext1Q` isNothing)
allJust :: (Data d) => d -> Bool
allJust = and . gmapQ (const True `ext1Q` isJust)
allLeft :: (Data d) => d -> Bool
allLeft = and . gmapQ (const True `ext1Q` isLeft)
CheckIfAllFieldsAreNothing.hs:18:35: error:
• Could not deduce (base-4.16.3.0:Data.Typeable.Internal.Typeable
a0)
arising from a use of ‘ext1Q’
from the context: Data d
bound by the type signature for:
allLeft :: forall d. Data d => d -> Bool
at CheckIfAllFieldsAreNothing.hs:17:1-32
or from: Data d1
bound by a type expected by the context:
forall d1. Data d1 => d1 -> Bool
at CheckIfAllFieldsAreNothing.hs:18:23-49
The type variable ‘a0’ is ambiguous
• In the first argument of ‘gmapQ’, namely
‘(const True `ext1Q` isLeft)’
In the second argument of ‘(.)’, namely
‘gmapQ (const True `ext1Q` isLeft)’
In the expression: and . gmapQ (const True `ext1Q` isLeft)
|
18 | allLeft = and . gmapQ (const True `ext1Q` isLeft)
Attempts: There is no "Type Class" application, so I can't "assign" a Typeable (Either a b) constraint.
Of course,
ext1Q :: (Data d, Typeable t) => (d -> q) -> (forall e. Data e => t e -> q) -> d -> q
ext2Q :: (Data d, Typeable t) => (d -> q) -> (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q) -> d -> q
(forall e. Data e => t e -> q)
is suitable for isNothing
/ isJust
while (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q)
is suitable for isLeft
/ isRight
.
I just need to choose the right type extension of queries for different type constructors.