![](/img/trans.png)
[英]Two parameter functions in type class instances of higher kinded types in Scala, how to translate this simple Haskell code to Scala?
[英]How does Haskell differentiate between difference possible type class instances
如果我使用错误的名称,请道歉。 我的问题来自对比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和乘法,所以我们可以提供2个类型,每个实现一个。 在Scala中,如果两个实现都隐含在范围内并具有相同的优先级,则会导致编译错误。 在这种情况下,我们可以简单地手动传递正确的实例,并且将解决错误。
对于这种情况,Haskell的等价物是什么? 如果有两个Int实例是Monoid,那么如何选择使用哪个实现呢?
Haskell对于任何实际上都是Num
实例(包括Int
类型)类型类: Sum
和Product
类型只有两个newtype包装器。 因此, Sum
是一个加成的monoid, Product
类型是乘法下的monoid。 取自实际来源:
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中的模块中,不能有两个相同类型和类型类的实例。 如果在两个不同的模块中有两个实例然后导入这两个模块,则尝试使用该实例将导致编译错误。
因此,选择使用哪个实例的唯一方法是仅导入导入一个提供实例的模块。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.