3

予想通り、これはうまくいきます:

foo :: Fractional a => a
foo = undefined                -- datum

bar :: Num a => a -> a
bar a = undefined              -- function

baz :: Fractional a => a
baz = bar foo                  -- application

everyFractionalも . であるため、これは期待どおりに機能しNumます。

したがって、予想どおり、Fractional引数をNumパラメーターに渡すことができます。

一方、以下も機能します。理由がわかりません。

foo :: Fractional a => a -> a
foo a = undefined              -- function

bar :: Num a => a
bar = undefined                -- datum

baz :: Fractional a => a
baz = foo bar                  -- application

意外と効く!ではないものがあり ます。NumFractionals

では、なぜNum引数をFractionalパラメーターに渡すことができるのでしょうか? 説明できますか?

4

4 に答える 4

6

タイプaインbaz :: Fractional a => aは、呼び出した人によって選択されますbaza選択した型がFractionalクラス内にあることを保証するのは、彼らの責任です。Fractionalは のサブクラスであるためNum、型aも である必要がありますNum。したがって、とbazの両方fooを使用できますbar

つまり、サブクラスの関係により、署名

baz :: Fractional a => a

本質的に同等です

baz :: (Fractional a, Num a) => a

foo, bar2番目の例は、実際には最初のものと同じ種類のものです。どちらが関数でどちらが引数であるかは問題ではありません。これも考慮することができます:

foo :: Fractional a => a
foo = undefined

bar :: Num a => a
bar = undefined

baz :: Fractional a => a
baz = foo + bar -- Works
于 2017-03-15T21:07:10.040 に答える
2

everyFractionalも であるため、期待どおりに動作しNumます。

それは正しいですが、これが何を意味するのかを正確に理解することが重要です。つまり、クラス内のすべてのFractionalクラス内にもあるということNumです。これは、オブジェクト指向または動的なバックグラウンドを持つ人が理解できる、「型のすべてのも型の中にある」という意味ではありませ。この場合、あなたの推論は理にかなっており、その値は関数で使用するには一般的ではありません。NumFractionalNumbarfoo
...または実際にはそうではありません.OO言語では数値階層が逆方向に機能するためです.他の言語では通常、数値を小数にキャストできますが、これらの言語では逆方向が発生します.これは、かなり強く型付けされたものでは自動的には行われません!

Haskell では、暗黙の型変換がまったく行われないため、これについて心配する必要はありません。まったく同じ型で作業します。この型は変数barが二次的なものです。ここで、 と の両方がこの単一の型をさまざまな方法で制約しますが、制約されるのは同じ型であるため、単純に両方の制約の組み合わせを取得します。これは、単独と同等です。fooabarfoo(Num a, Fractional a)Num a => Fractional aFractional a

于 2017-03-15T22:52:44.343 に答える