【问题标题】:Why does returning a String not count as an expression of type Show x?为什么返回 String 不能算作 Show x 类型的表达式?
【发布时间】:2021-03-28 17:12:15
【问题描述】:

谁能帮我理解为什么这段代码会产生编译错误?

hello :: (Show x) => x
hello = "Hello"

我认为String 具有Show 的属性,所以该函数应该能够返回String?这是错误消息:

• Couldn't match expected type ‘x’ with actual type ‘[Char]’
  ‘x’ is a rigid type variable bound by
    the type signature for:
      hello :: forall x. Show x => x
    at script.hs:160:1-25
• In the expression: "Hello"
  In an equation for ‘hello’: hello = "Hello"
• Relevant bindings include
    hello :: x (bound at script.hs:161:1)

【问题讨论】:

  • 你想完成什么?打印消息?将字符串转换为任何Show 类型?将任何Show 类型转换为字符串?
  • "Hello" 是一个字符串。通过使用签名Show x => x,您承诺对于作为Show 类型类成员的any x,您的函数将产生一个值,但该承诺不成立,因为您只有在x ~ String 时才这样做。
  • @Aplet123 我只是在玩泛型类型签名,并没有尝试转换任何东西。我唯一的目标是让它编译 :) 但我误解了泛型类型签名在 Haskell 中的实际含义。现在已经清理干净了。

标签: haskell


【解决方案1】:

您的类型签名并不代表您认为的意思。

从你的解释看来,你读到的这个签名类似于“我将返回一个 x 类型的值,它有一个 Show 的实例。我不会告诉你你到底是什么类型,但我保证它会有一个 Show"

的实例

但它真正的意思是“选择一个类型,任何类型,只要确保它有一个Show 的实例,我保证我会返回一个该类型的值

换句话说,当一个函数是泛型时,选择泛型类型是函数的调用者,而不是实现者。

【讨论】:

  • 这很有意义。我将 Haskell 类型类的概念与 Java 等命令式语言的接口混为一谈
  • 嗯,类型类实际上非常类似于Java 中的接口,尤其是在这种类型类只有一个参数的特殊情况下。您的函数大致相当于 Java 中的 X hello<X extends IShow>()
  • @FyodorSoikin 实际上,在这种情况下它们并不相同。 Java 不支持返回类型多态性,除非 OP 理解它。
  • this 不是返回类型多态方法@is7s 的示例吗?
  • 我没有说 Java 根本不支持返回类型多态性。我说它仅以 OP 理解的方式支持它。在您链接到的示例中,emptyList() 将始终返回一个具体值,并且不依赖于上下文。这相当于您答案中的第一个定义。并且不等同于返回类型多态性在类型类中的工作方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-15
  • 2011-01-13
  • 2013-03-15
相关资源
最近更新 更多