2016-04-16 25 views
0

私はハスケルを新しくしています。なぜこれがエラーを引き起こすのか不思議です。ハスケル推論型エラー

sumtest :: (Real a) => [a] -> a 
sumtest [] = 0 
sumtest (x:xs) = x + sumtest xs 

avgFunction :: (Integral a, Floating b) => [a] -> b 
avgFunction a = sumtest a/length a 

エラー

ERROR file:code/test1.hs:114 - Inferred type is not general enough 
*** Expression : avgFunction 
*** Expected type : (Integral a, Floating b) => [a] -> b 
*** Inferred type : (Integral Int, Floating Int) => [Int] -> Int 

----- sumtest aの結果はaを入力した

sumtest :: (Num a) => [a] -> a 
sumtest [] = 0 
sumtest (x:xs) = x + sumtest xs 

avgFunction :: (Integral a, Floating b) => [a] -> b 
avgFunction a = fromIntegral (sumtest a)/fromIntegral (length a) 
+0

avgFunction' 'の署名はあなたがB''にどこかA' 'から変換することを示唆しています。これはどこで起こるはずですか?現時点ではどこにでも変換を行わないため、エラーが発生します。ところで、一般的な「Num」からの変換は可能ではありません。どのようにして複素数を実際のものに "変換"しますか? – leftaroundabout

+0

編集を参照してください - そうですね、整数を取り入れて潜在的に小数点以下の平均値を求めたいと思います。 –

答えて

3
  • パー受け入れられる回答の下にワーキングコード----。これはIntegralタイプです。従って、ではありません。
  • length aの結果はIntです。これはIntegralタイプです。 (そしておそらくaは異なるものである。)

だからあなたはを分割することができないタイプがあり、どちらも2つの数値を、分割しようとしています。まあ、うまくいかないのですか?

幸いにも、数字を変換できます。いくつかの言語は暗黙のうちに(実際には、すべての種類の怪物†)、ハスケルではありません。さて、それを行うには、関数を持っていることを確認してください! hoogle is your friend

avgFunction a = fromIntegral (sumtest a)/fromIntegral (length a) 


&短剣。 ですが、はをIntまたはDoubleにそれぞれ変換する必要がある場合があります。です。また、Pythonのように、暗黙的なコンバージョンを保守的に行うと、が悪いとは思われません。しかし、のような暗黙の変換は、HaskellのようなHindley-Milner型のシステムでは機能しません。


もう1つ注意してください。これらの制約は実際には不必要に強いです。以下で十分である:

avgFunction :: (Real a, Fractional b) => [a] -> b 
avgFunction a = realToFrac (sumtest a)/realToFrac (length a) 

この方法では、関数は入力としてだけではなく、結果としてDoubleできるようになります。 (そしておそらく、それは何が起こっているかを理解することも簡単です。)

0

(これは本当にleftaroundabout's answerのコメント/拡張機能ですが、実際にコメントができるようにより多くのフォーマットが必要です。)


モジュールData.FunctionはA提供関数onを使用すると、別の関数の引数のそれぞれに適用する関数を指定できます。この場合、

avgFunction a = (sumtest a) ./ (length a) 
       where (./) = (/) `on` fromIntegral 

それは少し長く、実際のですが、それは、ローカルに定義された./オペレータはあなたが型変換定型コードを離れて抽象化したアルゴリズムを集中することができますという意味では間違いなく明確です。


そしてControl.Arrowを使用して、この楽しい小さな宝石でもあります:

avgFunction = sum &&& length >>> uncurry ((/) `on` fromIntegral) 
+0

これは、関数の署名を '[Int] - > b'に制限することに注意してください。 – leftaroundabout