3

そのため、私は Haskell を学習している最中であり、型/型クラス関連のエラーに陥ることがよくあります。かなり明らかなばかげた間違いもあれば、haskell が自分にはふさわしくないと感じさせるものもあります。とにかく、私はこのコードを持っています...

pfactors' ps n
    | p > (sqrt n) = []
    | m == 0 = p : (pfactors' ps q)
    | otherwise = pfactors' (tail ps) n where
        p = head ps
        (q, m) = divMod n p

pfactors = pfactors' primes

main = print $ pfactors 14

(いくつかの背景: pfactors 関数は、数値を取り、指定された数値の素因数である素数のリストを返すことになっています。primes素数の無限リストです)

これは私にこのエラーを与えます:

p47.hs:10:11:
    Ambiguous type variable `a' in the constraints:
      `Floating a' arising from a use of `pfactors'' at p47.hs:10:11-26
      `Integral a' arising from a use of `primes' at p47.hs:10:21-26
    Possible cause: the monomorphism restriction applied to the following:
      pfactors :: a -> [a] (bound at p47.hs:10:0)
    Probable fix: give these definition(s) an explicit type signature
                  or use -XNoMonomorphismRestriction

p < (sqrt n)と関係のある唯一のパーツであるため、これはパーツの問題であることがわかりましたFloating。すべてに変更すると正常にp < n動作し、正しい答えが得られます。でもどうしても平方根で確認したいのですがどうすればいいですか?

ところで、これは宿題ではありません。気が付けば、projecteuler.net の 47 番目の問題を解決しようとしているところです。

助けてくれてありがとう。

そして、上記のプロジェクトオイラー問題の解決策を私に教えないでください。私はできる限り自分でやりたいです:)。ありがとう。

4

3 に答える 3

6

あなたの問題は...まあ...整数値と浮動小数点値を比較できないことです:-)整数と浮動小数点の間の変換を明示的に示す必要があります。関数はsqrt :: (Floating a) => a -> a浮動小数点数で動作しますが、主に整数を扱っているため、無料で使用することはできません。次のようなことを試してください:

pfactors' ps n
    | p > (floor $ sqrt $ fromIntegral n) = []
    | m == 0 = p : (pfactors' ps q)
    | otherwise = pfactors' (tail ps) n where
        p = head ps
        (q, m) = divMod n p

ここでは、 を使用fromIntegral :: (Integral a, Num b) => a -> bして整数を別のものに変換し、それを への引数として使用できるようにしますsqrt。次に、floorfloat 値を整数に戻すように言います (これは切り捨てられることに注意してください!)。

次に、トップレベルの宣言に型シグネチャを追加する習慣を身に付けることをお勧めします。言語をよりよく理解できるようになるだけでなく、そうしないと、単型性の制限に違反する可能性があります。

于 2010-12-11T05:16:02.643 に答える
5

解決策はすでに提供されていますが、何が起こっているのかをさらに明確にしたいと思います。

特に、型クラスは型ではありません。Integral 値または Floating 値を持つことはできません。それらは型ではなく、型クラスです。これは、オブジェクト指向のサブタイピングとは異なります。

のような署名Integral a => a -> a -> aは、「2 つの整数引数を取り、何らかの整数値を返す関数」を意味するものではありません。「a 型の 2 つの値を取り、a 型の値を返す関数。また、a 型は Integral のインスタンスでなければならない」という意味です。両者の違いは重要です。引数と戻り値の両方が同じ型であることを覚えておくことは非常に重要です。「a」は、型シグネチャ内でその意味を変えることはできません。

では、これはどういう意味ですか?

まず第一に、型が Integral と Floating の両方のインスタンスであってはならないというアプリオリな要件はありません。そのような型があれば、変換は必要ありません。ただし、これらの各型クラスのセマンティックな意味により、単一の型が意味のある方法で両方のインスタンスになることは困難です。

第二に、型クラスについて話す方法にはもう少し注意する必要があります。これらは、オブジェクト指向のサブタイピングとは根本的に異なります。概念の違いにより、用語の違いもあります。用語を正確に使用することで、違いを理解し、他の人とコミュニケーションを取ることができます。

では、質問をどのように表現すればよいでしょうか。「Integer を Floating のインスタンスに変換して元に戻すにはどうすればよいですか?sqrt :: Floating a => a -> a関数を使用して、その結果を Integer 値と比較する必要があります。」のようなものです。

于 2010-12-11T08:50:52.943 に答える
0

あなたはすでにあなたの答えを得ています、しかし多分これは機能の同様の問題を避けるのを助けるでしょう:

http://www.haskell.org/haskellwiki/Converting_numbers

背景がほとんど動的型付け言語にある人として、私は時々同じ問題を抱えているので、Haskell関数を書くときは常に署名から始めることを習慣にしました。それは、私が何を期待し、どこが間違っているのかを推論するのに本当に役立ちます。

于 2010-12-11T10:20:01.800 に答える