我特別試圖定義半羣和'是'半羣的和類型,並通常使用ScalaCheck來檢查半羣的關聯屬性。爲在ScalaCheck中保存一個`Numeric`的case類創建一個任意實例?
我第一次在Haskell中寫過這個,因爲我發現先用Haskell語法先思考這些東西,然後再將它們轉換爲Scala,這很容易。
所以在Haskell,我寫這GHCI工作如下:
newtype Sum a = Sum a deriving (Show, Eq)
instance Num a => Num (Sum a) where
(+) (Sum x) (Sum y) = Sum (x + y)
class Semigroup a where
(<>) :: a -> a -> a
instance Num a => Semigroup (Sum a) where
(<>) = (+)
instance Arbitrary a => Arbitrary (Sum a) where
arbitrary = fmap Sum arbitrary
semigroupAssocProp x y z = (x <> (y <> z)) == ((x <> y) <> z)
quickCheck (semigroupAssocProp :: Num a => Sum a -> Sum a -> Sum a -> Bool)
我試圖創造一些斯卡拉大致相當。到目前爲止,我中有你看看下面:
trait Semigroup[A] {
def |+|(b: A): A
}
case class Sum[A: Numeric](n: A) extends Semigroup[Sum[A]] {
def |+|(x: Sum[A]): Sum[A] = Sum[A](implicitly[Numeric[A]].plus(n, x.n)
}
val semigroupAssocProp = Prop.forAll { (x: Sum[Int], y: Sum[Int], z: Sum[Int]) =>
(x |+| (y |+| z)) == ((x |+| y) |+| z)
}
val chooseSum = for { n <- Gen.chooseNum(-10000, 10000) } yield Sum(n)
// => val chooseSum Gen[Sum[Int]] = org.scalacheck.Gen$$anon$<some hash>
我失去了對如何創建一個更通用Sum[Numeric]
一個Arbitrary
實例,或至少Gen[Sum[Numeric]]
以及如何創建一個更通用的semigroupAssocProp
,可以採取一個類型爲S
的x,y和z,其中S extends Semigroup[T]
,其中T
是任何具體類型。
我真的想在功能上儘可能接近我在Scala中編寫的Haskell版本。問題的
當我嘗試在Scala REPL中運行代碼時,出現聲明Sum類型不帶參數的錯誤。 def sum(a:Sum [A],b:Sum [A]):Sum [A] = Sum(隱含地[Numeric [A]]。加上(an,bn))' – josiah
@josiah'Sum' case類和對象是一對伴侶,必須一起定義,如果您只是複製並粘貼到REPL中,則不會發生這種情況,但您可以使用' :粘貼'來一起定義它們。 –
您的Scala版本確實看起來像'instance Num a => Semigroup(Sum a)其中'比問題中的版本更多。 – pedrofurla