【发布时间】:2014-05-07 16:18:13
【问题描述】:
抱歉,如果我使用了错误的名称。我的问题来自对比 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 的实例,如何选择使用哪个实现?
【问题讨论】:
-
一个无关紧要的吹毛求疵:如果您想将 Int,*,1 视为幺半群,则无需排除零。
-
你说得对,是在考虑组。更正了问题,谢谢!