なぜこれが機能しないのですか:-
(length [1,2,3,4]) + 3.2
これが機能している間:-
2+3.3
最初のケースでは結果は Int+Float ですが、2 番目のケースでも同じではないこと、または Haskell が 2 番目のケースの型を :- Num+Num であると自動的に推測することを理解していますが、それは行いません最初のケースでは?
なぜこれが機能しないのですか:-
(length [1,2,3,4]) + 3.2
これが機能している間:-
2+3.3
最初のケースでは結果は Int+Float ですが、2 番目のケースでも同じではないこと、または Haskell が 2 番目のケースの型を :- Num+Num であると自動的に推測することを理解していますが、それは行いません最初のケースでは?
Haskellが暗黙の型変換を行うことは決してありません。+
同じ型の 2 つの数値に対してのみ機能し、結果としてその型も提供します。+
あなたの(length [1,2,3,4]) + 3.2
例で見たように、他の使用法はエラーです。
ただし、数値リテラルは Haskell でオーバーロードされます。2
は、任意の数値型に3.3
することも、任意の小数型にすることもできます。したがって、Haskell は式2 + 3.3
を確認すると、「数値」と「分数」の両方である型を見つけようとし、加算が機能するように両方の数値をその型として扱うことができます。
より正確に言えば+
、型を持っていNum a => a -> a -> a
ます。2
単独で は typeNum a => a
であり3.3
、単独で は typeFractional a => a
です。これら 3 つの型をまとめると、式では2 + 3.3
両方の数値に type を指定できます。これはFractional a => a
、すべてのFractional
型もNum
型であり、これも型 を満たすためです+
。(この式を GHCi に入力するa
と、 として埋められDouble
ます。これは、GHC が評価するために型をデフォルトで何かに設定する必要があるためです)
式(length [1,2,3,4]) + 3.2
では、3.2
はまだオーバーロードされています (単独では type になりますFractional a => a
)。しかしlength [1,2,3,4]
、タイプがありInt
ます。一方の側は固定具象型であるため、型を満たす唯一の方法は、もう一方の型を で+
埋めることですが、それは制約に違反します。になる方法はありません。したがって、この式は適切に型付けされていません。a
Int
Fractional
3.2
Int
ただし、適用することにより、任意のIntegral
型 (そのうちの 1 つ) を任意のInt
型に変換できます(実際には、これは整数リテラルのようなものを任意の数値型として扱うことができる方法です)。それでうまくいきます。 Num
fromIntegral
2
(fromIntegral $ length [1,2,3,4]) + 3.2
最初のケースでは、あなたが述べたように、length [1,2,3,4]
明示的にであり、暗黙的にまたはインスタンスInt
に変換することはできません。2 番目の例では、明示的な型指定はありません。したがって、Haskell は適切な型が のインスタンスであると推測できます。Haskell 2010 report の対応するセクション (§6.4.1) で、数値リテラルがコンパイラによってどのように処理されるかを確認できます。Float
Fractional
Fractional
回避策:(fromIntegral $ length [1,2,3,4]) + 3.2
2 番目の例のような整数リテラルは、コンパイラによって2
暗黙的に扱われます。これは、戻り値の型が多態的でfromInteger 2
あるため、必要な数値型に変換されることを意味します。fromInteger
この場合、Float
が使用されます。ただし、length [1,2,3,4]
はリテラルではなく typeInt
であるため、その値を明示的に変換する必要があります。