Ich versuche speziell Semigruppe und einen Sum-Typ zu definieren, der eine Semigruppe ist und die Associative-Eigenschaft der Semigroup generisch mit ScalaCheck prüft.Erstellen Sie eine beliebige Instanz für eine Fallklasse, die in ScalaCheck eine `Numeric` enthält?
Ich habe das zuerst in Haskell geschrieben, weil ich es leichter finde, zuerst an diese Dinge in der Haskell-Syntax zu denken und sie dann in Scala zu übersetzen.
So in Haskell, schrieb ich die folgenden, die in GHCi funktioniert:
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)
Ich versuche, etwas entspricht in etwa in Scala zu erstellen. Bisher habe ich was sehen Sie unten:
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>
Ich bin verloren, wie eine generische Sum[Numeric]
eine Arbitrary
Instanz zu erstellen, oder zumindest einen Gen[Sum[Numeric]]
und wie ein allgemeineres semigroupAssocProp
zu erstellen, die nehmen könnte ein x, y und z vom Typ S
, wobei S extends Semigroup[T]
, wobei T
irgendein Betontyp ist.
Ich versuche wirklich, so nah an der Haskell-Version zu kommen, die ich in Scala geschrieben habe.
Wenn ich versuche, Ihren Code in der Scala REPL auszuführen, erhalte ich einen Fehler, der behauptet, dass der Sum-Typ keine Parameter akzeptiert. ': 18: Fehler: Sum.type nimmt keine Parameter def add (a: Summe [A], b: Summe [A]): Summe [A] = Summe (implizit [numerisch [A]]. plus (an, bn)) ' –
josiah
@josiah Die Fallklasse und das Objekt 'Summe' sind ein Begleitpaar und müssen zusammen definiert werden, was nicht passiert, wenn Sie einfach in die REPL kopieren und einfügen, aber Sie können' : einfügen, um sie zusammen zu definieren. –
Ihre Scala-Version sieht folgendermaßen aus: 'Instanz Num a => Semigroup (Summe a) where' mehr als die Version in der Frage. – pedrofurla