web-dev-qa-db-ja.com

Haskellのあいまいな発生-回避する方法?

私は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
43
me2

タイプは明らかに異なりますが、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つのスタイルの ポリモーフィック関数 を使用できます。

  • Parametric polymorphism、これにより、関数は構造的に同一の抽象的な方法で任意の型を操作できます
  • Ad-hoc polymorphism、これにより、関数は定義されたタイプのセットのいずれに対しても構造的に異なる方法で操作できますが、できれば、意味的には同じです

パラメトリックポリモーフィズムは、Haskellおよび関連言語における標準的な(そして選択肢としては好ましい)アプローチです。アドホックポリモーフィズムは、他のほとんどの言語の標準であり、「関数のオーバーロード」などの名前で行われ、多くの場合、同じ名前で複数の関数を記述することによって実装されます。

Haskellでは、type classesによってアドホックな多態性が有効になり、関連するすべてのアドホックな多態性関数とインスタンスでクラスを定義する必要がありますオーバーロード解決で使用される型に対して明示的に宣言されます。 インスタンス宣言の外で定義された関数は、たとえそれらの型が明確で参照が明確であっても、アドホックポリモーフィックになることはありません。

そのため、同じ名前の複数の非型クラス関数が異なるモジュールで定義されている場合、両方のモジュールを修飾なしでインポートすると、いずれかの関数を使用しようとするとエラーが発生します。 Data.ListData.Map、およびData.Setの組み合わせは、この点で特に悪質であり、Data.Listの一部はPreludeによってエクスポートされるため、標準的な方法は(Nathanとして)サンダースは言う)常に資格のある他の人をインポートします。

24
C. A. McCann