我有以下数据类型:
data PValue = IV Int | BV Bool | SV String
deriving (Show, Eq)
我想编写一个函数,从 Int、Bool 或 String 生成 PValue,例如:
> loadVal 3
IV 3
> loadVal True
BV Bool
> loadVal "Ha"
SV "Ha"
由于 loadVal 的参数是多态的,我尝试创建一个类:
class PValues v where
loadVal :: v -> PValue
instance PValues Int where
loadVal v = IV v
instance PValues Bool where
loadVal v = BV v
instance PValues String where
loadVal s = SV s
这似乎有效,除了 Int:
> loadVal "Abc"
SV "Abc"
> loadVal False
BV False
> loadVal 3
<interactive>:8:1:
No instance for (PValues v0) arising from a use of `loadVal'
The type variable `v0' is ambiguous
Note: there are several potential instances:
instance PValues String -- Defined at Types.hs:22:10
instance PValues Bool -- Defined at Types.hs:19:10
instance PValues Int -- Defined at Types.hs:16:10
In the expression: loadVal 3
In an equation for `it': it = loadVal 3
<interactive>:8:9:
No instance for (Num v0) arising from the literal `3'
The type variable `v0' is ambiguous
Note: there are several potential instances:
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 8 others
In the first argument of `loadVal', namely `3'
In the expression: loadVal 3
In an equation for `it': it = loadVal 3
据我了解,这是因为 3
本身的类型不明确(可能是 Int
、Float
等)。有没有办法强制进行这种类型推断,而无需在调用站点中显式注释它?
最佳答案
在此处扩展@AndrewC 的评论。为了使 loadVal 3
工作,请执行以下操作
实例化时的类型转换:
instance PValues Integer where
loadVal v = IV (fromInteger v)
现在,如果您想让它与 Text
类型一起使用并且不希望您的
用户要显式注释它,请提供 String
的两个实例
以及文本
:
data PValue = IV Int | BV Bool | SV Text
deriving (Show, Eq)
instance PValues String where
loadVal s = SV (pack s)
instance PValues Text where
loadVal s = SV s
对于编译器能够推断出您的输入的地方
Text
数据类型,它不必经过 pack
开销。
关于haskell - 对于这个例子,如何在 Haskell 中获得更好的多态类型推断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27399978/