无法显示 haskell 中实例函数的结果
cannot show result from an instance function in haskell
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
可以用正确的实例构造 any 类型的键,所以它具有多态类型 k1 :: KEY k => k
。这很好,因为您可以将 k1
与不同具体类型的键进行比较......在您的情况下,您已经尝试使用 k2 :: PrimaryKey
,但您也可以使用 k1 == k3
k3 :: SomeOtherKeyType
,前提是 SomeOtherKeyType
也是 KEY
class 的一个实例——在这种情况下,k1
也将简单地“接管”类型 SomeOtherKeyType
.
不利的一面是 k1
没有 特定的 类型。它实际上可能是 any 适用类型,但编译器应该如何知道你想要哪个?当使用 ==
时,它的两边必须是相同的类型,所以在一侧有一个具体的类型就足够了,但是单独使用 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 (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
可以用正确的实例构造 any 类型的键,所以它具有多态类型 k1 :: KEY k => k
。这很好,因为您可以将 k1
与不同具体类型的键进行比较......在您的情况下,您已经尝试使用 k2 :: PrimaryKey
,但您也可以使用 k1 == k3
k3 :: SomeOtherKeyType
,前提是 SomeOtherKeyType
也是 KEY
class 的一个实例——在这种情况下,k1
也将简单地“接管”类型 SomeOtherKeyType
.
不利的一面是 k1
没有 特定的 类型。它实际上可能是 any 适用类型,但编译器应该如何知道你想要哪个?当使用 ==
时,它的两边必须是相同的类型,所以在一侧有一个具体的类型就足够了,但是单独使用 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)