2016-10-15 28 views
-2

ケース1は機能しましたが、ケース2が失敗したため、以下のタイプの推論に実際に従うことはできませんでした。なぜですか? OOPでハスケルで型推論に従うには?

ghci> :t sqrt . maximum . map (+1) -- case 1 

(Floating c, Ord c) => [c] -> c 

ghci> :t sqrt . maximum . map length -- case 2 

Could not deduce (Floating Int) arising from a use of ‘sqrt’ 
from the context (Foldable t) 
bound by the inferred type of it :: Foldable t => [t a] -> Int 

@EDIT

NumはUsusallyにすべてのsubtypes例えばための下限でありますIntおよびFloat。従って、Intは、Numが修飾型であれば推論的に許容可能ですが、その逆もありません。

さらに、Cのような言語では、組み込みの数値変換は自動的にケースをより低い精度から高い精度まで満たすことができます。 IntからFloatまでです。対照的に、HM type systemのハスケルでは、Numは、instancesのすべてについてclassであり、例えば、HM type systemを有するハスケルでは、のすべてについてclassである。例えば、Intおよびsubclassesである。 Floating。修飾された型は、祖先と子孫の間で双方向に推論できます。 NumからInt,Floatingまたはその逆であるが、IntFloatingの間ではない。ケース2を改善する

Intは、まずfromIntegralによってNumに適合又はNum生成するData.List.genericLengthを発揮しなければならない - sqrtが必要であることFloatingための推論修飾タイプ。

ghci> :t (+) 
Num a => a -> a -> a 

ghci> :t 1.1 
Fractional a => a 

ghci> :i Fractional 
class Num a => Fractional a 
instance Fractional Float 
instance Fractional Double 

ghci> :t 1 
Num a => a 

ghci> :t length [1] 
Int 

ghci> :i Int 
instance Num Int  
instance Real Int 
instance Integral Int 

ghci> :t 1.1 + 1   -- case 1 
Fractional a => a 

ghci> :t 1.1 + length [1] -- case 2 
No instance for (Fractional Int) arising from the literal ‘1.1’ 
+1

'length'関数は' Int'を返しますが、 'sqrt'は' Floating'インスタンスを持つ型が必要です。 'Dataから' genericLength'を使ってみてください。代わりに 'List'を使用します。これは、' Num'インスタンスで任意の型を生成できます。 –

+0

要約が間違っています。型クラスは型ではありません。 NumからInt、またはIntからFloatingに変換することはできません。これらはリンゴとオレンジです。型クラスは型を制約します。たとえば、 'Floating a => a - > a - > a'のように、' a'はFloatingインスタンスを持たなければなりません。 'Float'は、' Int'はしません。 – erisco

+0

@erisco、ポイントは 'type inference'ですが、私の言葉はあなたに' type class'と 'type'の間の変換を考えさせるかもしれません。 – sof

答えて

4

1は、数の任意のタイプにすることができ、+は、数の任意のタイプで動作することができます、のは、以下の型推論を追跡するために、前述のポイントを適用してみましょう。 maximumについても同様です。したがって、maximum . map (+1)は、任意のタイプの番号のリストを取り、その結果と同じタイプの番号を生成することができる関数です。これには、整数と浮動小数点数の両方が含まれます。

しかし、lengthは、Intを具体的に生成します。他のタイプの番号を生成することはできません。したがって、maximum . map lengthは任意のリストを取り、他の数値タイプではなくタイプIntの結果を生成できます。

sqrtは、浮動小数点数の引数が必要です。したがって、最初のケースでは、浮動小数点数のリストを提供しなければならないことが推測されるので、maximum . map (+1)の結果はsqrtに渡すことができる浮動小数点数になります。

Intは浮動小数点型ではないため、maximum . map lengthInt以外のものを生成できないため、2番目のケースは単純に機能しません。このため、エラーが発生します。

fromIntegral関数を使用して、lengthの結果を任意の数値型に変換して、2番目のコードを機能させることができます。

+0

編集した投稿を適切に要約したかどうかを調べることができますか?ありがとう! – sof