ケース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
またはその逆であるが、Int
とFloating
の間ではない。ケース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’
'length'関数は' Int'を返しますが、 'sqrt'は' Floating'インスタンスを持つ型が必要です。 'Dataから' genericLength'を使ってみてください。代わりに 'List'を使用します。これは、' Num'インスタンスで任意の型を生成できます。 –
要約が間違っています。型クラスは型ではありません。 NumからInt、またはIntからFloatingに変換することはできません。これらはリンゴとオレンジです。型クラスは型を制約します。たとえば、 'Floating a => a - > a - > a'のように、' a'はFloatingインスタンスを持たなければなりません。 'Float'は、' Int'はしません。 – erisco
@erisco、ポイントは 'type inference'ですが、私の言葉はあなたに' type class'と 'type'の間の変換を考えさせるかもしれません。 – sof