scala - Haskell 如何区分不同的可能类型类实例

标签 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 -> 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 和加法的 Monoid,也可以是具有 1 和乘法的 Monoid,因此我们可以提供 2 个类型类,每个实现一个。在 Scala 中,如果两个实现在作用域内都是隐式的并且具有相同的优先级,这将导致编译错误。在这种情况下,我们可以简单地手动传递正确的实例,错误将得到解决。

这种情况下 Haskell 的等价物是什么?如果 Int 有两个实例是 Monoid,那么如何选择使用哪个实现?

最佳答案

对于实际上是 Num 实例的任何类型,Haskell 仅具有两个 newtype 包装器。 (包括 Int 类型)类型类:SumProduct .所以,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)

关于scala - Haskell 如何区分不同的可能类型类实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23523098/

相关文章:

java - 使用 "with"关键字在 scala 中向上转换外部 java 库会产生类型不匹配错误

haskell - 用 Haskell 编写 Haskell 解释器

Scala的collection的sliding()在窗口大小大于step时不一致

generics - Scala 中的 Monad 特性

haskell - Haskell 中的交换函数

haskell - `Ord` 实例 `on` 一些函数

Haskell——双向类实例类型含义或 GADT 存在类型限定?

haskell - Clojure 中的协议(protocol)和多方法在多态性方面不如 Haskell 中的类型类强大的原因是什么?

scala - scala中的require和assert之间如何选择

haskell - 在 Haskell 中获取玫瑰树的根