【问题标题】:Couldn't Match Expected Type Against Inferred Type, Rigid Type Variable Error无法将预期类型与推断类型匹配,刚性类型变量错误
【发布时间】:2019-04-21 14:00:33
【问题描述】:

这个函数有什么问题?

test :: Show s => s
test = "asdasd"

String 是Show 类的一个实例,所以看起来是正确的。

错误是

src\Main.hs:224:7:
    Couldn't match expected type `s' against inferred type `[Char]'
      `s' is a rigid type variable bound by
          the type signature for `test' at src\Main.hs:223:13
    In the expression: "asdasd"
    In the definition of `test': test = "asdasd"

【问题讨论】:

    标签: haskell


    【解决方案1】:

    test :: Foo a => a 表示“对于任何作为Foo 实例的类型,test 是该类型的值”。因此,在任何可以使用X 类型值的地方,其中X 是一个实例Foo,你可以使用Foo a => a 类型的值。

    test :: Num a => a; test = 42 之类的东西之所以有效,是因为 42 可以是 IntIntegerFloat 类型的值,或者是 Num 的任何其他实例。

    但是 "asdasd" 不能是 Int 或任何其他 Show 的实例 - 它只能是 String。因此,它与 Show s => s 类型不匹配。

    【讨论】:

    • 在带有OverloadedStrings语言扩展和导入Data.String的GHC中,您也可以使用签名test :: IsString s ⇒ s
    • test :: Num => atest :: Num 有什么不同吗?
    • @mcb 这取决于您如何定义“不同”。它们都是错误,所以在这个意义上它们是相同的。但是,您可能会争辩说,它们是不同的,因为它们可能是不同错误的结果。那就是test :: Num => a 可能是一个简单的错字的结果(忘记=> 之前的a),而test :: Num 可能是代码作者认为Num 是一个类型而不是一个类型的结果类。
    • 此类问题的任何替代方案,或者以这种方式解决问题从根本上是错误的?这是我的情况,我有类型类IDP 和函数fromString :: IDP a => String -> Maybe a 意味着将字符串转换为已知的IDP,之后我可以像fetchValue :: IDP a => Maybe a -> IO () 一样将值传递给下游
    【解决方案2】:

    是的,StringShow 的一个实例。但这不允许使用字符串作为 abritary Show 值。 1 可以是Num a => a,因为有1 :: Integer1 :: Double1 :: Word16 等。如果"asdasd" 可以是Show a => a 类型,则有"asdasd" :: Bool"asdasd" :: String"asdasd" :: Int 等。没有。因此,"asdasd" 不能是 Show a => a 类型。字符串常量的类型并没有比String 更通用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      相关资源
      最近更新 更多