class (Eq k, Ord k, Show k) => KEY k where
keyBuild :: NumId -> NumId -> NumId -> k
keyDummy :: k
keyFromList :: [NumId] -> k
-- keyGenerate :: (DATAPOOL p) => p -> Int -> [k] -- p = Pool k e s
newtype PrimaryKey = PK (NumId, NumId, NumId) deriving (Eq, Ord, Show)
instance KEY PrimaryKey where
keyBuild k0 k1 k2 = PK (k0,k1,k2)
keyDummy = PK (0,0,0)
keyFromList is = keyFromList (take 3 (is ++ (replicate 3 0)))
keyGenerate p cnt = let
ks = keys p
pks = map (\l -> keyFromList (randomize l)) (replicate cnt 3)
in pks
in ghci I do
let k1 = keyBuild 1 2 3
let k2 = PK (1,2,3)
k1 == k2
True
k2
PK (1,2,3)
and get True and the value of k2 as expected, but
k1
231:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘it’
prevents the constraint ‘(KEY a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instance exist:
instance [safe] KEY PrimaryKey -- Defined at Work
Expected PK(1,2,3) PrimaryKey has deriving (Eq, Ord, Show) so what have I done wrong or missed?
You have not given k1
a fixed type. Because keyBuild
can construct a key of any type with the right instance, it has the polymorphic type k1 :: KEY k => k
. That's nice because you can then compare k1
to keys of different concrete types... in your case, you've tried it with k2 :: PrimaryKey
, but you could just as well do k1 == k3
with k3 :: SomeOtherKeyType
, provided SomeOtherKeyType
is also an instance of the KEY
class – in that case, k1
would simply also “take over” the type SomeOtherKeyType
.
The flip side is that k1
has no particular type. It may in fact be any applicable type, but how is the compiler supposed to know which you want? When using ==
it must be the same type on both sides, so there it's sufficient to have a concrete type on one side, but all by itself k1
is ambiguous.
It so happens that in your module there is only one instance that matches, namely KEY PrimaryKey
but in general there would be many (or zero!) such instances. It would be strange if the compiler just picked one arbitrarily, wouldn't it?
So if you want to show k1
, you need to manually pick one type. Easy enough to do, just add a local signature:
*Main> let k1 = keyBuild 1 2 3
*Main> :t k1
k1 :: KEY k => k
*Main> k1 :: PrimaryKey
PK (1,2,3)