私はHaskellBookに取り組んでおり、の任意のインスタンスを作成することになりましたnewType Comp
。コードは以下のとおりです
instance Show (Comp a) where
show f = "Unicorns!!"
newtype Comp a =
Comp { unComp :: (a -> a) }
instance (Semigroup a) => S.Semigroup (Comp a) where
(Comp fx) <> (Comp fy) = Comp (fx . fy)
instance (CoArbitrary a, Arbitrary a) => Arbitrary (Comp a) where
arbitrary = do
f <- Test.QuickCheck.arbitrary
return (Comp f)
type CompAssoc = String -> Comp String -> Comp String -> Comp String -> Bool
compAssoc :: (S.Semigroup a, Eq a) => a -> Comp a -> Comp a -> Comp a -> Bool
compAssoc v a b c = (unComp (a <> (b <> c)) $ v) == (unComp ((a <> b) <> c) $ v)
とテスト
main :: IO ()
main = do
quickCheck (compAssoc :: CompAssoc)
私の質問は、任意のインスタンスを中心に展開します。に渡される関数を生成していreturn (Comp f)
ます。私は(完全な理由ではありませんが)これをCoArbitraryにスコープする必要があることを理解しています。そのことは、に渡された場合でもreturn (Comp f)
ありCoArbitrary
、それはどのようにもすることができArbitrary
?これらの制約は、関数のパス/戻り値の型と関数自体の両方を参照しているように思われます。私は少し混乱しています。
これは、初心者向けの、高レベルの非常におそらく、根本的な詳細に不正確な関係の説明Arbitrary
とCoArbitrary
。
記事https://begriffs.com/posts/2017-01-14-design-use-quickcheck.htmlはより良い説明を提供しますが、それはApplicativeとFunctorを使用しており、私はまだそこにいるのでまだそこに到達していません「TheHaskellBook」のセミグループの章。
あなたからの関数を生成したい場合はa -> b
、b
のインスタンスを持っている必要がありますArbitrary
。とにかくランダムなものを生成するので、いつものように必要Gen b
です。ただし、通常の関数と同じようにこれを変更する必要がありますb
。つまり、のような関数に別の値を渡すdouble
と、別の応答が期待されます。しかし、ランダムに基づいてジェネレータを変更するにはどうすればよいa
でしょうか。b
そもそもランダムなsを生成する方法を考えると、それはと関係がありnumbers
ます。つまり、ランダムが必要な場合b
(たとえば、Int)、私は乱数を生成するだけです。簡単なピーシー。ランダムな文字列?乱数から始めて、ASCII文字に変換します。必要な他のデータ型と同じであり、quickcheckはArbitrary
それを実行する多くのインスタンスを提供します。
さて、基本的には数字です。他の数値を取得してから、たとえば、乗算/減算/加算/除算することで、これらの数値を変更できます。または他の数学演算。しかし、どうすれば他の番号を取得できますか?そこで登場CoArbitrary
します!のインスタンスが必要であるとタイプをマークするとCoArbitrary
、事実上、「タイプのジェネレーターを変更(追加/変更など)できるように、タイプを数に減らすことができる必要がありますb
。したがって、 typea
は文字列です。たとえば、その文字列を数値に減らし、それをgen fortype b
に渡して、Gen fortypeがを生成するために使用する数値b
に対してmult/add/etc
操作を実行できるようにします。b
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加