4

なぜこれが機能しないのですか:-

(length [1,2,3,4]) + 3.2

これが機能している間:-

2+3.3

最初のケースでは結果は Int+Float ですが、2 番目のケースでも同じではないこと、または Haskell が 2 番目のケースの型を :- Num+Num であると自動的に推測することを理解していますが、それは行いません最初のケースでは?

4

3 に答える 3

13

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ます。一方の側は固定具象型であるため、型を満たす唯一の方法は、もう一方の型を で+埋めることですが、それは制約に違反します。になる方法はありません。したがって、この式は適切に型付けされていません。aIntFractional3.2Int

ただし、適用することにより、任意のIntegral型 (そのうちの 1 つ) を任意のInt型に変換できます(実際には、これは整数リテラルのようなものを任意の数値型として扱うことができる方法です)。それでうまくいきます。 NumfromIntegral2(fromIntegral $ length [1,2,3,4]) + 3.2

于 2013-08-08T08:32:35.513 に答える
10

最初のケースでは、あなたが述べたように、length [1,2,3,4]明示的にであり、暗黙的にまたはインスタンスIntに変換することはできません。2 番目の例では、明示的な型指定はありません。したがって、Haskell は適切な型が のインスタンスであると推測できます。Haskell 2010 report の対応するセクション (§6.4.1) で、数値リテラルがコンパイラによってどのように処理されるかを確認できます。FloatFractionalFractional

回避策:(fromIntegral $ length [1,2,3,4]) + 3.2

于 2013-08-08T08:02:41.477 に答える
8

2 番目の例のような整数リテラルは、コンパイラによって2暗黙的に扱われます。これは、戻り値の型が多態的でfromInteger 2あるため、必要な数値型に変換されることを意味します。fromIntegerこの場合、Floatが使用されます。ただし、length [1,2,3,4]はリテラルではなく typeIntであるため、その値を明示的に変換する必要があります。

于 2013-08-08T08:09:03.193 に答える