2016-07-27 4 views
0

プロジェクトでは、リストとハッシュを合計する必要があります。私はHaskellはM.Map IntApplicativeのインスタンスであると考えているエラーを理解していれば、次のエラーData.Lazy.MapをNumのインスタンスにマップする

<interactive>:2:37: 
    Overlapping instances for Num (M.Map Int Int) 
     arising from a use of ‘+’ 
    Matching instances: 
     instance (Ord k, Num b) => Num (M.Map k b) 
     -- Defined at Tweak.hs:15:10 
     instance (Applicative f, Num b) => Num (f b) 
     -- Defined at Tweak.hs:7:10 
    In the expression: 
     (M.fromList [(2 :: Int, 3 :: Int)]) + (M.fromList [(1, 2)]) 
    In an equation for ‘it’: 
     it = (M.fromList [(2 :: Int, 3 :: Int)]) + (M.fromList [(1, 2)]) 

を生成GHCiの中で、この(M.fromList [(2 :: Int, 3 :: Int)]) + (M.fromList [(1, 2)]) を実行Numインスタンス

{-# LANGUAGE FlexibleInstances #-} 
module Tweak where 
import Data.List 
import qualified Data.Map.Lazy as M 
import Control.Applicative 

instance (Applicative f, Num b) => Num (f b) where 
    negate  = fmap negate 
    (+)   = liftA2 (+) 
    (*)   = liftA2 (*) 
    fromInteger = pure . fromInteger 
    abs   = fmap abs 
    signum  = fmap signum 

instance (Ord k, Num b) => Num(M.Map k b) where 
    negate  = fmap negate 
    (+)   = M.unionWith (+) 
    (*)   = M.unionWith (*) 
    fromInteger = undefined 
    abs   = fmap abs 
    signum  = fmap signum 

の2次の宣言になってしまいました。それはそうではないようです。 :i M.Map Int収量

type role M.Map nominal representational 
data M.Map k a 
    = containers-0.5.6.2:Data.Map.Base.Bin {-# UNPACK #-}containers-0.5.6.2:Data.Map.Base.Size 
             !k 
             a 
             !(M.Map k a) 
             !(M.Map k a) 
    | containers-0.5.6.2:Data.Map.Base.Tip 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance (Ord k, Num b) => Num (M.Map k b) 
    -- Defined at Tweak.hs:15:10 
instance (Eq k, Eq a) => Eq (M.Map k a) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance Functor (M.Map k) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance (Ord k, Ord v) => Ord (M.Map k v) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance (Ord k, Read k, Read e) => Read (M.Map k e) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance (Show k, Show a) => Show (M.Map k a) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance Foldable (M.Map k) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance Traversable (M.Map k) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
instance Ord k => Monoid (M.Map k v) 
    -- Defined in ‘containers-0.5.6.2:Data.Map.Base’ 
data Ability = ... | Int | ... -- Defined at Character.hs:60:41 

data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in ‘GHC.Types’ 
instance Bounded Int -- Defined in ‘GHC.Enum’ 
instance Enum Int -- Defined in ‘GHC.Enum’ 
instance Eq Int -- Defined in ‘GHC.Classes’ 
instance Integral Int -- Defined in ‘GHC.Real’ 
instance Num Int -- Defined in ‘GHC.Num’ 
instance Ord Int -- Defined in ‘GHC.Classes’ 
instance Read Int -- Defined in ‘GHC.Read’ 
instance Real Int -- Defined in ‘GHC.Real’ 
instance Show Int -- Defined in ‘GHC.Show’ 

このエラーは本当にわかりません。どんな助けも大歓迎です。

+5

Haskellは制約を調べる前にインスタンスの解決を行いますので、実際にインスタンスforallall f bを定義しています。 Num(f b) 'は非常に一般的で、おそらくあなたが望むものではありません。制約はインスタンスが選択された後にのみチェックされます*。 –

+0

はい、これは確かに私が欲しいものではありません。どのようにこれを解決するための任意のアイデア? – Ronan

+0

これはあなたが求めているものかもしれませんが、あなたがここで求めているものを提供することは、高いコストがかかります。種類* - > *の上に他のNumインスタンスはありません。より良い仕組みは、 'newtype ANum f a = ANum(f a)'を作成し、インスタンスをnewtypeに焼くことです。誰かが書いた* - > *何かの可能性のあるnumインスタンスと競合することはありません。ユーザーはデータをあなたのユースケースと互換性のある形式にまとめることができます。 'newtype Poly a = Poly [a]'はインスタンスと重複しますが、確かに[] 'のアプリケーションを使って行うべきではありません! –

答えて

3

なぜこの種のインスタンスを定義するのが良い考えであると人々はいつ考えるのですか?

タイプクラスはすべて、約が安全に汎用関数を書くことを許可しています。これは特定のメソッドを指定することによって機能し、一緒に再生する方法に関する明確な法律です。同様に、モナド法則など。
Numは、ringという数学的概念を基本的に表し、さらにmetricを定義するために多少心を尽くしたアプローチを表します。これは実際にの数値タイプに制限されている場合にのみ有効です。 インスタンスの場合と同様に、の番号のコレクションは、これらの法律をまったく遵守しない場合があります。

だから、そのようなインスタンスから離れてください。私はあなたがそれらを使用しようとしている方法は、とにかく汎用アルゴリズムとは関係がないと思う...あなたはM.unionWith (+)のconsise演算子名を持っていたいなら、あなたは型クラスを乱用している。単純な単形演算子(+<)を定義することができます(または、少なくとも、アドホック多形ではありません - それは(Num n, Ord k) => M.Map k nで動作すると大丈夫です)。

クラス多型が必要と思われる場合は、適切なクラスを探してください! Additiveは意味をなさないでしょう。 VectorSpace class:私は、私は通常をお勧めしてが近いあなたのNumインスタンスのアイデアへの意味であるもの実際にある第三の可能性を、言及する必要があり、すでにit actually has an instance for Map ...


を見よ。 Numのように、これは実際にはファンクタではなく、Numとは異なり、absなどのファズがありません。

Additiveとは異なり、このパッケージはMapインスタンスは付属していませんが、ベクトル空間の^+^は、あなたが実際にa -> Map k Int値を追加することができて、そこにちょうどthaのためa dedicated typeだと関数インスタンスが標準ですので。

+0

'Applicative'の' Num'宣言は標準です。私は数値的操作を点で指示する。 'M.Map k n'は' k'から 'n'までの関数に過ぎないので、それをポイント上でポイント定義することも完全に意味があります。 'Additive'のコードを見ると、' M.Map'の宣言はかなり似ています。しかし、私はそれが 'M.Map Int Char 'に私には意味をなさない追加を与えるので好きではありません。 また、私はリングの構造を参照していません、私は正確に私が望むものでそれらのオブジェクトの基本的な計算を実行するコンピュータを可能にする低レベルのカテゴリとして 'Numを参照してください。 – Ronan

+0

'Num'はどのように[カテゴリ](https://en.wikipedia.org/wiki/Category_(数学))ですか?それは本当に私には意味をなさない。 - 'Additive'は' Map Int Char 'に加えて、あなたにその印象を与えましたか?あるNumerインスタンスをあるファンクタ内のPointwise-Numオペレーションにリフトするだけです。 – leftaroundabout

+0

よく 'Num'は集合の集合なので、この場合でもカテゴリを呼び出す習慣があるのですが、この場合でも変形は簡単です。 私は 'Map Int b 'が任意の' b'のために追加的であるべきだと思うと宣言したので、私はこの気持ちを得ました。しかし、なぜ私が間違っているのか理解しました。 Haskellの構文はまだ私にはあまり馴染みがないので、実際に何をしていたのか分かりませんが、かなりエレガントです。指摘していただきありがとうございます! – Ronan

関連する問題