在本例中,如何在Haskell中获得更好的多态类型推断?

在本例中,如何在Haskell中获得更好的多态类型推断?,haskell,polymorphism,type-inference,Haskell,Polymorphism,Type Inference,我有以下数据类型: data PValue = IV Int | BV Bool | SV String deriving (Show, Eq) 我想编写一个函数,从Int、Bool或字符串生成PValue,如下所示: > loadVal 3 IV 3 > loadVal True BV Bool > loadVal "Ha" SV "Ha" 由于loadVal的参数是多态的,因此我尝试创建一个类: class PValues v where

我有以下数据类型:

data PValue = IV Int | BV Bool | SV String
            deriving (Show, Eq)
我想编写一个函数,从Int、Bool或字符串生成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
>loadVal“Abc”
SV“Abc”
>loadVal False
BV假
>负荷值3
:8:1:
没有因使用“loadVal”而产生的(PValues v0)实例
类型变量“v0”不明确
注意:有几个潜在的例子:
实例PValues字符串--在Types.hs:22:10中定义
实例PValues Bool——在Types.hs:19:10处定义
实例PValues Int——在Types.hs:16:10处定义
在表达式中:loadVal 3
在“it”的方程式中:it=loadVal 3
:8:9:
没有由文字“3”产生的(Num v0)实例
类型变量“v0”不明确
注意:有几个潜在的例子:
实例Num Double——在“GHC.Float”中定义
实例Num Float——在“GHC.Float”中定义
实例积分a=>Num(GHC.Real.Ratio a)
--在“GHC.Real”中定义
…加上其他8个
在'loadVal'的第一个参数中,即'3'
在表达式中:loadVal 3
在“it”的方程式中:it=loadVal 3

我理解这是因为
3
本身是不明确的类型(可以是
Int
Float
,等等)。有没有一种方法可以在不在调用站点显式注释的情况下强制执行此类型推断?

在此处展开@AndrewC的注释。要使
loadVal 3
工作,请执行以下操作 实例化时的类型转换:

instance PValues Integer where
  loadVal v = IV (fromInteger v)
现在,如果您想让它与
文本一起工作,请键入
并且不希望
用户要显式地对其进行注释,请为
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
开销。

您可以尝试将
实例PValues设置为整数,其中loadVal v=IV(fromInteger v)
?然后,您可能会发现默认设置为Integer会让您达到目的。@AndrewC可能无法像Integer
中的
那样工作,它需要
Integer
@AndrewC这是一个很好的解决方法,而且确实有效。你应该将此作为答案发布。:)@Sibi我很高兴任何人(当然包括你)都能写出来——我真的应该提交一份令人兴奋的文具订单!我保证会给愿意的志愿者投上一票,特别是如果他们@reply me让我知道已经完成了。@donatello Oh-我认为GHC的最新版本允许对
IsString
typeclass进行默认声明,所以你可以尝试将
default(String)
default(Text)
添加到你的文件中。谢谢@Sibi,像往常一样写得很好。