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
在 ghci 中我愿意
let k1 = keyBuild 1 2 3
let k2 = PK (1,2,3)
k1 == k2
True
k2
PK (1,2,3)
并按预期得到 True 和 k2 的值,但是
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
预期PK(1,2,3) PrimaryKey 有派生(Eq、Ord、Show),那么我做错或错过了什么?
最佳答案
您尚未为 k1
指定固定类型。由于 keyBuild
可以使用正确的实例构造任何类型的 key ,因此它具有多态类型 k1::KEY k => k
。这很好,因为您可以将 k1
与不同具体类型的键进行比较......在您的情况下,您已经使用 k2::PrimaryKey
进行了尝试,但您可以也可以将 k1 == k3
与 k3::SomeOtherKeyType
一起使用,前提是 SomeOtherKeyType
也是 KEY
的实例class – 在这种情况下,k1
也将简单地“接管”类型 SomeOtherKeyType
。
另一方面,k1
没有特定类型。事实上它可能是任何适用的类型,但是编译器如何知道你想要哪个类型呢?当使用 ==
时,两侧必须是相同的类型,因此一侧有一个具体类型就足够了,但 k1
本身是不明确的。
碰巧在你的模块中只有一个匹配的实例,即KEY PrimaryKey
,但通常会有很多(或零个!)这样的实例。如果编译器随意选择一个,那会很奇怪,不是吗?
所以如果你想显示k1
,你需要手动选择一种类型。很容易做到,只需添加本地签名即可:
*Main> let k1 = keyBuild 1 2 3
*Main> :t k1
k1 :: KEY k => k
*Main> k1 :: PrimaryKey
PK (1,2,3)
关于class - 无法显示 haskell 中实例函数的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46090803/