Haskell 使Data.Lazy.Map成为Num的实例

Haskell 使Data.Lazy.Map成为Num的实例,haskell,Haskell,在一个项目中,我经常需要总结列表和散列。最后,我给出了以下两个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 n

在一个项目中,我经常需要总结列表和散列。最后,我给出了以下两个
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
运行这个
(M.fromList[(2::Int,3::Int)])+(M.fromList[(1,2)])
在ghci中产生以下错误

<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)])

我真的不明白这个错误。欢迎任何帮助。

为什么人们总是认为定义此类实例是个好主意

类型类都是关于允许安全地编写泛型函数的。这是通过指定某些方法和明确的法律来实现的,这些方法和法律应该如何配合。比如,单子定律等。
Num
基本上代表了a的数学概念,加上一种半心半意地定义a的方法。只有当您将其限制为数字类型时,这才有效。一般的数字集合,如您的
应用程序
实例,可能根本不遵守这些规则


所以,请远离这种情况。我怀疑你试图使用它们的方式与通用算法无关。。。如果您只想为
M.unionWith(+)
拥有一个一致的运算符名,那么您就是在滥用类型类。你可以只定义一个简单的单态运算符
(++为什么人们总是认为定义这种实例是个好主意

类型类都是关于允许安全地编写泛型函数的。这是通过指定某些方法和关于它们应该如何一起使用的明确规则来实现的。例如,monad法则等。
Num
基本上代表了a的数学概念,加上一种半心半意地定义a的方法。只有当实际上,您将其限制为数字类型。一般的数字集合,如您的
应用程序
实例,可能根本不遵守这些规则


因此,请远离此类实例。我怀疑您尝试使用它们的方式与通用算法无关……如果您只是想为
M.unionWith(+)
提供一个一致的运算符名称,那么您就是在滥用类型类。您只需定义一个简单的单态运算符
(+Haskell在查看约束之前执行实例解析,因此实际上您已经为所有fB.Num(fB)定义了一个实例
,它非常通用,可能不是您想要的。只有在选择实例后才会检查约束。是的,这肯定不是我想要的。知道如何解决这个问题吗?这可能是您要求的,但在这里提供您要求的,成本很高。没有其他Num实例在任何类型上*->*。a beTter机制是生成一个<代码>新的ANAMF A= ANUM(FA),然后将你的实例烘焙成NeXType。然后,你不会与任何其他可能的NUM实例发生冲突,比如任何人都会写,并且用户可以将它们的数据封装成与你的用例兼容的形式。考虑<代码> newtype Poly A= PyL[A]
它将与您的实例重叠,但肯定不应该使用Applicationfor[]`!Haskell在查看约束之前执行实例解析,因此您实际上已经为所有f b.Num(f b)定义了一个实例
,它非常通用,可能不是您想要的。只有在选择实例后才会检查约束。是的,这肯定不是我想要的。知道如何解决这个问题吗?这可能是您要求的,但在这里提供您要求的,成本很高。没有其他Num实例在任何类型上*->*。a beTter机制是生成一个<代码>新的ANAMF A= ANUM(FA),然后将你的实例烘焙成NeXType。然后,你不会与任何其他可能的NUM实例发生冲突,比如任何人都会写,并且用户可以将它们的数据封装成与你的用例兼容的形式。考虑<代码> newtype Poly A= PyL[A]它将与您的实例重叠,但肯定不应该使用applicative for[]`!我对
Applicative
Num
声明是规范的。我以逐点方式提升数值运算。
M.mapkn
只是从
k
n
的一个函数,因此在其上逐点定义运算也非常有意义。仔细查看
additional
声明中的代码在for
M.Map
上,它与我的非常相似。但是我不喜欢它,因为它给了
M.Map Int Char
一个对我来说毫无意义的加法。另外,我也没有提到环结构,我认为
Num
是一个低级类别,允许计算机对那些对象执行基本计算,这正是我想要的。
Num
a如何?这对我来说真的没有意义。-
Additive
没有给
Map Int Char
一个加法,是什么给了你这样的印象?它只是将
Num
实例提升到某个函子中的逐点Num操作,也就是说,正是你所需要的。嗯
Num
是集合,所以我得到了把它称为一个范畴的习惯,即使在这种情况下,态射也是微不足道的。我有这种感觉是因为声明
instance Ord k=>Additive(Map k)其中
,这让我认为,
Map Int b
应该是任何
b
的加法。但我理解了为什么我错了。Haskell语法对我来说还是有点不熟悉,所以我花了一段时间才理解它到底在做什么,这非常优雅。谢谢你指出!事实上,答案只是部分令人满意工厂。我确实可以通过使用
^+^
添加
Map k Int
,但我不能在适当提升授权的情况下添加函数
a->Map k Int
。你有什么解决方法吗?我对
Applicative
Num
声明是规范的。我以点方式提升数值操作。
 M.地图
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’