5

私はまだ Haskell に取り組もうとしていますが、私をかなり悩ませていることに気付きました。

「Haskell を学んで大成功を収めよう!」という本の中で パターン マッチングでのガードの使用を示すこの部分があります。本の場合、それは人の 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

java や c# Boy で .toString が行うように "show" が機能することを期待するの
は間違っていました。

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では文字列です...これはまさに型シグネチャが私が返さなければならないと言っているものです

それで、私はここで何を間違えましたか?

4

2 に答える 2

9

型シグネチャを次のように変更します。

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

メンバー関数を使用したいのでshow、型クラスからShow; しかし、関数制約でそれを指定していないため、ghci にはそれが正しいと推測する方法がありません。

于 2013-06-28T22:20:30.727 に答える
2

RealFloat は表示可能な型ではありません。表示制約を追加する必要があります。

于 2013-06-28T22:20:46.797 に答える