2016-07-22 4 views
4

私が取得していますGHCiのfactorPairs 18で関数を呼び出すと、私は与えられた数あいまいなタイプは `の使用に起因する」変数` A0'

factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)] 
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0] 

要因ペアを返すために、以下の機能を持っています

* Ambiguous type variable `a0' arising from a use of `it' 
     prevents the constraint `(Floating a0)' from being solved. 
     Probable fix: use a type annotation to specify what `a0' should be. 
     These potential instances exist: 
     instance Floating Double -- Defined in `GHC.Float' 
     instance Floating Float -- Defined in `GHC.Float' 
    * In the first argument of `print', namely `it' 
     In a stmt of an interactive GHCi command: print it 

の実行時エラーが、私はハードGHCiの

map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0] に機能をコーディングすることができますし、すべての問題を持っていないが、私はできないようです私の機能が失敗している理由を理解する。私はghciがどのタイプをprintと呼ぶのか分かりませんが、解決策を見つけるのは苦労していると私に伝えようとしています。

+0

次のように試してください:「y map」(y | y < - [1(ceiling $ sqrt 18)]、18 'rem' y == 0 ]をGHCiに入力して推論する。 – Mephy

+1

あなたのタイプ署名を再考する必要があります。 'Floating'と' Integral'の両方の型を指定できますか?関数を単調にすることをお勧めします。例えば、 'Double'を使い、必要なときにのみ一般化してください。 –

+0

@ ThomasM.DuBuisson私は実際にそれを楽しみのために考えていました。浮動小数点型と整数型の_reasonable_型がありますか?また、型に基づいて関数を検索するためにhoogleやhayooを使用できるように、インスタンスに基づいて型を検索する方法はありますか? – Alec

答えて

5

これは、数値リテラルがHaskellでオーバーロードされているという事実と関係があります。 map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0]ghciに入力すると、sqrtの引数である18は、デフォルトでDoubleになり、その他はIntegerに設定されます。しかし

、あなたは一種類のみを持っているnのすべてのインスタンスを強制

factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)] 
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0] 

書きます。次に、これらの制約をすべて満たすデフォルトの数値型(実際には数値型)は存在しないため、GHCは試行する可能性のあるインスタンスについてあなたに伝えます。ソリューションはfromIntegralを追加し、制約を緩めることである:

factorPairs:: Integral a => a -> [(a, a)] 
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt $ fromIntegral n)], n `rem` y == 0] 
4

タイプエラーを取り除くための別の方法はsqrtの使用を排除することです。 Haskellは怠惰なので、[1..n]を反復して、除数があなたの商よりも大きいときに止めることができます。

factorPairs :: Integral a => a -> [(a, a)] 
factorPairs n = takeWhile (uncurry (>=)) [ (n `div` d, d) | d <- [1..n], n `mod` d == 0] 

uncurry (>=)\(q, d) -> q >= dを書くだけの空想の方法です。

これをモナド形式で書くと、divModを使用して商と剰余を1つの関数で得ることができます。

factorPairs n = takeWhile (uncurry (>=)) $ do 
       d <- [1..n] 
       let (q, r) = n `divMod` d 
       guard $ r == 0 
       return (q, d) 
関連する問題