私はGHCIで次のことを行います。
:m + Data.Map
let map = fromList [(1, 2)]
lookup 1 map
GHCIは、マップが(Map Integer Integer)であることを認識しています。では、型が明確で回避できるのに、なぜPrelude.lookupとData.Map.lookupのあいまいさを主張するのでしょうか。
<interactive>:1:0:
Ambiguous occurrence `lookup'
It could refer to either `Prelude.lookup', imported from Prelude
or `Data.Map.lookup', imported from Data.Map
> :t map
map :: Map Integer Integer
> :t Prelude.lookup
Prelude.lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
> :t Data.Map.lookup
Data.Map.lookup :: (Ord k) => k -> Map k a -> Maybe a
タイプは明らかに異なりますが、Haskellは名前のアドホックオーバーロードを許可しないため、プレフィックスなしで使用するlookup
を1つだけ選択できます。
一般的な解決策は、修飾されたData.Map
をインポートすることです。
> import qualified Data.Map as Map
その後、あなたは言うことができます
> lookup 1 [(1,2), (3,4)]
Just 2
> Map.lookup 1 Map.empty
Nothing
通常、Haskellライブラリは、Preludeからの名前の再利用を回避するか、またはそれらの全体を再利用します。 Data.Map
は秒の1つであり、著者はそれを修飾してインポートすることを期待しています。
[編集:ephemientのコメントを含める]
プレフィックスなしでData.Map.lookup
を使用する場合は、Prelude.lookup
を暗黙的にインポートするため、非表示にする必要があります。
import Prelude hiding (lookup)
import Data.Map (lookup)
これは少し奇妙ですが、Data.Map.lookup
全体を使用していて、データ構造がすべてマップであり、リストになっていない場合に役立つことがあります。
もう少し一般的な注意として、これは最初私を混乱させたものです-それで、ネイサン・サンダースが言ったことを繰り返し強調してみましょう:
Haskellは名前のアドホックなオーバーロードを許可していません
これはデフォルトで当てはまりますが、最初は意外にも自明ではないようです。 Haskellでは、2つのスタイルの ポリモーフィック関数 を使用できます。
パラメトリックポリモーフィズムは、Haskellおよび関連言語における標準的な(そして選択肢としては好ましい)アプローチです。アドホックポリモーフィズムは、他のほとんどの言語の標準であり、「関数のオーバーロード」などの名前で行われ、多くの場合、同じ名前で複数の関数を記述することによって実装されます。
Haskellでは、type classesによってアドホックな多態性が有効になり、関連するすべてのアドホックな多態性関数とインスタンスでクラスを定義する必要がありますオーバーロード解決で使用される型に対して明示的に宣言されます。 インスタンス宣言の外で定義された関数は、たとえそれらの型が明確で参照が明確であっても、アドホックポリモーフィックになることはありません。
そのため、同じ名前の複数の非型クラス関数が異なるモジュールで定義されている場合、両方のモジュールを修飾なしでインポートすると、いずれかの関数を使用しようとするとエラーが発生します。 Data.List
、Data.Map
、およびData.Set
の組み合わせは、この点で特に悪質であり、Data.List
の一部はPreludeによってエクスポートされるため、標準的な方法は(Nathanとして)サンダースは言う)常に資格のある他の人をインポートします。