1

私はHaskellを学んでいて、型システムを理解しようとして立ち往生しています。

入力に対してシリーズ「HalforThreePlusOne」の長さを返す関数を作成しようとしています。これが再帰的アプローチを使用した関数での私の試みです(関数は積分入力に対してのみ有効です):

hotpo :: (Integral a) => a->a
hotpo n = hotpoHelper n 1

hotpoHelper:: (Integral a) => a->a->a
hotpoHelper 1 n = n
hotpoHelper num count
    | even num = hotpoHelper (truncate (num/2)) (count+1)
    | otherwise = hotpoHelper (3*num+1) (count+1)

これは、GHC6.12.3でこのファイルを読み込もうとしたときに発生するエラーです。

test.hs:8:30:
    Could not deduce (RealFrac a) from the context (Integral a)
      arising from a use of `truncate' at test.hs:8:30-45
    Possible fix:
      add (RealFrac a) to the context of
        the type signature for `hotpoHelper'
    In the first argument of `hotpoHelper', namely
        `(truncate (num / 2))'
    In the expression: hotpoHelper (truncate (num / 2)) (count + 1)
    In the definition of `hotpoHelper':
        hotpoHelper num count
                      | even num = hotpoHelper (truncate (num / 2)) (count + 1)
                      | otherwise = hotpoHelper (3 * num + 1) (count + 1)

take (truncate (5/2)) [1,2,3]動作するので、このエラーメッセージを理解できません。どこが間違っているのですか?

4

1 に答える 1

10

Haskellの/演算子は、浮動小数点除算に使用されます。本当に浮動小数点除算とを使用しtruncateたい場合は、最初にを使用して浮動小数点数に変換します。発生するエラーは、整数に対して小数除算を使用できないことを示しています(5/2は、コンパイラが両方の数値の浮動小数点型を推測するため、機能します)。ただし、この関数を使用すると、やりたいことがはるかに簡単に実行できます。これは通常、関数名をバッククォートで囲むことにより、中置で使用されます(これはすべてのHaskell関数で機能します)。fromIntegralnumdiv

| even num = hotpoHelper (num `div` 2) (count+1)
于 2010-11-17T10:02:21.080 に答える