1

具体的には、Semigroup と「Semigroup である」Sum タイプを定義し、ScalaCheck を使用して一般的に Semigroup の Associative プロパティをチェックしようとしています。

最初にこれを 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)

Scalaでほぼ同等のものを作成しようとしています。これまでのところ、私はあなたが以下に示すものを持っています:

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>

より一般的な、または少なくとも aのArbitraryインスタンスを作成する方法と、型whereの x、y、および z を取ることができるより一般的なものを作成する方法について、具体的な型であることに迷っています。Sum[Numeric]Gen[Sum[Numeric]]semigroupAssocPropSS extends Semigroup[T]T

Scala で書いた Haskell のバージョンに機能をできる限り近づけようとしています。

4

1 に答える 1