HaskellのCoArbitrary

tesserakt

私は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これらの制約は、関数のパス/戻り値の型と関数自体の両方を参照しているように思われます私は少し混乱しています。

tesserakt

これは、初心者向けの、高レベルの非常におそらく、根本的な詳細に不正確な関係の説明ArbitraryCoArbitrary

記事https://begriffs.com/posts/2017-01-14-design-use-quickcheck.htmlはより良い説明を提供しますが、それはApplicativeとFunctorを使用しており、私はまだそこにいるのでまだそこに到達していません「TheHaskellBook」のセミグループの章。

あなたからの関数を生成したい場合はa -> bbのインスタンスを持っている必要があります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]

編集
0

コメントを追加

0

関連記事