Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Haskell如何区分不同类型的类实例_Scala_Haskell_Typeclass - Fatal编程技术网

Scala Haskell如何区分不同类型的类实例

Scala Haskell如何区分不同类型的类实例,scala,haskell,typeclass,Scala,Haskell,Typeclass,如果我使用了错误的名称,请道歉。我的问题来自于Scala和Haskell语法的对比。考虑: class Monoid a where mempty :: a mappend :: a -> a -> a instance Monoid Int where mempty = 0 mappend a b = a + b sigma :: (Monoid a) => Int -> Int -> (Int -> Int) -> (Int -

如果我使用了错误的名称,请道歉。我的问题来自于Scala和Haskell语法的对比。考虑:

class Monoid a where
  mempty :: a
  mappend :: a -> a -> a

instance Monoid Int where 
  mempty = 0
  mappend a b = a + b

sigma :: (Monoid a) => Int -> Int -> (Int -> Int) -> (Int -> a) -> a
sigma a b inc comp =
  if a > b then mempty else mappend (comp a) (sigma (inc a) b inc comp)
在Scala中,它可能类似于:

trait Monoid[A] {
  def mempty: A
  def mappend(a1: A, a2: A): A
}

class IntMonoid extends Monoid[Int] {
  def mempty = 0
  def mappend(a: Int, b: Int) = a + b
}

def sigma[A](a: Int, b: Int, inc: Int => Int, comp: Int => a)
            (implicit m: Monoid[A]): A =
  if (a > b) m.mempty else m.append(comp(a), sigma(inc(a), b, inc, comp))
现在,Int可以是带0和加法的幺半群,也可以是带1和乘法的幺半群,所以我们可以提供2个类型类,每个实现一个。在Scala中,如果两个实现都是隐式的,并且具有相同的优先级,这将导致编译错误。在这种情况下,我们可以简单地手动传递正确的实例,错误将得到解决


在这种情况下,Haskell的等效值是多少?如果有两个Int是幺半群的实例,那么如何选择使用哪个实现呢?

Haskell只是为任何实际是
Num
(包括
Int
type)实例的类型提供了两个newtype包装器:typeclass:
Sum
Product
。所以,
Sum
是加法下的幺半群,
Product
type是乘法下的幺半群。取自实际来源:

newtype Sum a = Sum { getSum :: a }
        deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num)

instance Num a => Monoid (Sum a) where
        mempty = Sum 0
        Sum x `mappend` Sum y = Sum (x + y)

newtype Product a = Product { getProduct :: a }
        deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num)

instance Num a => Monoid (Product a) where
        mempty = Product 1
        Product x `mappend` Product y = Product (x * y)

Haskell中的一个模块中不能有两个相同类型和类型类的实例。如果在两个不同的模块中有两个实例,然后导入这两个模块,则尝试使用该实例将导致编译错误


因此,选择使用哪个实例的唯一方法是只导入一个提供实例的模块。

而且由于newtype是一个不可操作的类型,所有的
Sum
Product
构造函数都会被编译掉。但请务必指出它是全局性的。如果您的任何依赖项导入了提供实例的模块,那么您也可以看到该模块。这就是孤立实例被轻视的原因。如果只在1)定义数据类型时或2)定义类时定义实例,则可以保证不能为同一数据类型定义两个不同的实例。一个不相关的细节:如果希望将Int、*、1视为幺半群,则无需排除零。没错,您考虑的是组。更正了问题,谢谢!