【问题标题】:Why isn't show treated as a conversion in haskell?为什么在haskell中不将show视为转换?
【发布时间】:2013-06-28 22:12:52
【问题描述】:

我仍然非常想进入 haskell,但我注意到一些让我非常恼火的事情。

"Learn You a Haskell for Great Good!" 的书中有这部分展示了在模式匹配中使用守卫,在这本书中它是一个计算人的 bmi 的小函数,它有点像这样(部分稍作改动以不侵犯版权或其他):

bmiCalc :: (RealFloat a) => a -> a -> String
bmiCalc weight height
    | bmi <= 18.5 = "skinny"
    | bmi <= 25.0 = "normal"
    | bmi <= 30.0 = "fat"
    | otherwise   = "obese"
    where bmi = weight / height ^ 2

这一切都很好,代码像宣传的那样工作,但我想,如果它还显示它计算的 bmi 和文本呢?

所以我重写了代码:

bmiCalc :: (RealFloat a) => a -> a -> String
bmiCalc weight height
    | bmi <= 18.5 = "skinny, " ++ show bmi
    | bmi <= 25.0 = "normal, " ++ show bmi
    | bmi <= 30.0 = "fat, "    ++ show bmi
    | otherwise   = "obese, "  ++ show bmi
    where bmi = weight / height ^ 2

期望“show”像 .toString 在 java 和 c# 中一样工作
男孩是我错了。

ghci 给了我这个严重的错误信息:

Could not deduce (Show a) arising from a use of `show'
from the context (RealFloat a)
  bound by the type signature for
             bmiCalc :: RealFloat a => a -> a -> String
  at file.hs:1:16-48
Possible fix:
  add (Show a) to the context of
    the type signature for bmiCalc :: RealFloat a => a -> a -> String
In the second argument of `(++)', namely `show bmi'
In the expression: "skinny, " ++ show bmi
In an equation for `bmiCalc':
    bmiCalc weight height
      | bmi <= 18.5 = "skinny, " ++ show bmi
      | bmi <= 25.0 = "normal, " ++ show bmi
      | bmi <= 30.0 = "fat, " ++ show bmi
      | otherwise = "obese, " ++ show bmi
      where
          bmi = weight / height ^ 2
Failed, modules loaded: none.

这是为什么呢?为什么它不允许我将似乎返回字符串的内容附加到字符串?我的意思是据我了解"skinny, " ++ show bmi 是一个字符串......这正是类型签名所说的我必须返回的内容

那么我在这里做错了什么?

【问题讨论】:

  • 您是否尝试过错误消息中的建议(在“可能修复”之后)?
  • 与 Java 相当的等价物是 showShow 接口的一个方法,而您的值 a 不需要实现该接口,因此存在编译时类型检查错误——在 Java 中会发生同样的事情。
  • 过去的情况是,类型类 RealFloatShow 作为其先决条件之一(通过 Num),但不久前这种情况发生了变化。 LYAH 在这方面已经过时(请参阅learnyouahaskell.com/types-and-typeclasses#typeclasses-101,搜索“加入 Num”)

标签: haskell type-signature


【解决方案1】:

将类型签名更改为:

bmiCalc :: (RealFloat a, Show a) => a -> a -> String

因为你要使用show的成员函数,来自Show类型类;但是你没有在函数约束中指定,ghci无法推断它是正确的。

【讨论】:

  • 有趣的是,我之前尝试过这样做,但没有成功......现在它以某种方式出现了......无论如何,谢谢!
  • 当您遇到此类错误时,最简单的方法是删除类型签名,在 ghci 中重新加载文件并输入 :t bmiCalc。这就是我在最后添加所有类型签名的方式。
【解决方案2】:

RealFloat 不是可展示的类型。您必须添加一个显示约束。

【讨论】:

    猜你喜欢
    • 2012-07-05
    • 1970-01-01
    • 2012-10-14
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    相关资源
    最近更新 更多