11

私は次のHaskellコードを持っています:

-- Problem 69

import ProjectEuler

phi :: Integer -> Integer
phi n = n * product [p - 1 | p <- primeDivisors n] `div` product [p | p <- primeDivisors n]
-- primeDivisors n is a list of the prime divisors of n

maxRatio :: (Int, Int, Double) -> (Int, Int, Double) -> (Int, Int, Double)
maxRatio t1@(_, _, x) t2@(_, _, y)
  | x > y = t1
  | otherwise = t2

main = print (foldl
                maxRatio
                (0, 0, 0.0)
                [(n, phi n, ratio) | n <- [2..max], let ratio = fromIntegral n / (fromIntegral (phi n))]
              )
    where max = 1000

これにより、次のエラーが発生します。

Couldn't match expected type `Int' with actual type `Integer'
In the expression: n
In the expression: (n, phi n, ratio)
In the third argument of `foldl', namely
  `[(n, phi n, ratio) |
      n <- [2 .. max],
      let ratio = fromIntegral n / (fromIntegral (phi n))]'

トリプル(0, 0, 0.0)では0はタイプだと思いIntます。この場合のように、0常にタイプですかInt、それともghciがタイプを推測していますか?後で、代わりIntにタイプするように強制するにはどうすればよいですか?Integerまたは、このエラーを引き起こす他の何かがありますか?

4

4 に答える 4

18

0Haskellは通常、必要な適切なタイプなど、数値リテラルのタイプを推測できます。これは、それらを渡す関数を認識しているためです。私が関数を持っていて、phi :: Integer -> Integer私が呼び出すphi 0場合、Haskellはその特定のものがで0あったに違いないことを知っていますInteger。;で関数を呼び出しても問題ありませんpho :: Int -> Intその特定はであると推測されます。pho 00Int

ただしInt、とIntegerは異なるタイプであり、特定の1つをとの0両方に渡すphi方法はありませんpho

あなたの問題は、maxRatio扱うタプルが(あなたによって)入力されているということです(Int, Int, Double)が、そのようなタプルの1つはとして構築されてい(n, phi n, ratio)ます。phiを取り、返すのでIntegernその式のはである必要がありIntegerます。しかし、それはでは機能しないmaxRatioため、エラーが発生します。

実際に必要なタイプ(Intまたは)に応じて、またはIntegerのタイプシグネチャを変更して、同じ種類の番号で機能するようにするだけです。Haskellは、文字通りに書かれたsは、それを機能させることができるものがあれば、その機能を実現するために必要な数値タイプであると判断します。phimaxRatio0

メッセージされたエラーは、それがであると予想され、実際にはであったことを具体的に示していることに注意してください。タプルについては言及されていません。多くの場合、型エラーは、コンパイラが指定した場所以外の場所で発生します(コンパイラが実行できるのは、推論のさまざまなチェーンが何かの型に一貫性のない要件を生成し、プロセス全体のどの部分が「間違っている」かを知る方法がないためです。 )、しかしこの場合、それはかなりうまくいきました。n(n, phi n, ratio)IntInteger(0, 0, 0.0)

Haskellは、不可解なエラーメッセージに対して(かなり正当化された)悪い担当者を受け取りますが、コンパイラが問題であると言っていることから始めて、それが不平を言っている事実がコードから生じる理由を理解しようとするのに大いに役立ちます。これは最初は苦痛になりますが、Haskellのエラーメッセージ(少なくともより単純なメッセージ)で基本的なリテラシーをすばやく開発し、これらの種類のエラーを非常に迅速に見つけるのに役立ちます。これにより、コンパイラは非常に強力なエラー検出になります。あなたのためのシステム。

于 2012-09-05T02:32:39.477 に答える
5

nIntのタイプが原因であると推測されていますmaxRatioが、タイプphiはそうあるべきだと言っていますInteger。最も簡単な修正は、maxRatio使用するタイプを変更するか、それらの値に触れないという理由Integerだけで変更することです。a

于 2012-09-05T02:10:13.077 に答える
3

推測されているので、の型アノテーションを変更するだけですmaxRatio。それでも、明示Intをに変更する必要がある場合はIntegertoInteger :: (Integral a) => a -> Integer

于 2012-09-05T02:25:43.063 に答える
1

型署名に一貫性がありません-全体に置き換えIntてください。Integer

于 2012-09-05T15:02:10.640 に答える