所以我有下面的代碼,我試圖讓它成為一個實體Arbitrary:
data MyData = I Int | B Bool
instance Arbitrary MyData where
arbitrary = do {
frequency [(1, return (I 1)),
(1, return (choose((B True), (B False))))]
}
但是,有了這個,我得到(可以理解的)錯誤:
Couldn't match type ‘Gen MyData’ with ‘MyData’
Expected type: Gen MyData
Actual type: Gen (Gen MyData)
我怎樣才能實作這一點?I 1另外,我想I用隨機回傳而不是 ( ) Int。但是,使用該arbitrary函式代替1會導致相同的錯誤。
uj5u.com熱心網友回復:
由于您似乎希望在建構式之間均勻分布I,因此B更簡單的解決方案是使用oneof而不是frequency:
data MyData = I Int | B Bool deriving (Eq, Show)
instance Arbitrary MyData where
arbitrary = oneof [genI, genB]
where genI = fmap I arbitrary
genB = fmap B arbitrary
genIand生成器通過將原始整數和布林值映射到各自的 case 建構式來使用andgenB的底層Arbitrary實體。IntBool
這是一組示例資料:
> sample (arbitrary :: Gen MyData)
B False
B False
I 2
B False
I 1
I 7
B False
B False
B True
I 7
B False
如您所見,它還可以選擇任意整數。
OP 中的代碼有幾個問題。第一個錯誤訊息是回傳型別是嵌套的。解決這個問題的一種方法是洗掉do符號。然而,這并不能解決問題。
即使您將其減少到以下內容,它也不會進行型別檢查:
instance Arbitrary MyData where
arbitrary =
frequency [(1, return (I 1)),
(1, choose(B True, B False))]
此嘗試會產生錯誤:
Q72160684.hs:10:21: error:
* No instance for (random-1.1:System.Random.Random MyData)
arising from a use of `choose'
* In the expression: choose (B True, B False)
In the expression: (1, choose (B True, B False))
In the first argument of `frequency', namely
`[(1, return (I 1)), (1, choose (B True, B False))]'
|
10 | (1, choose(B True, B False))]
| ^^^^^^^^^^^^^^^^^^^^^^^
該choose方法要求輸入是Random實體,但MyData事實并非如此。
如果您真的想使用frequency而不是oneof,最簡單的方法可能是首先開始oneof作業,因為您可以將frequency其視為oneof.
首先,為了使代碼更簡潔,我使用<$>了而不是fmap然后行內了兩個生成器:
instance Arbitrary MyData where
arbitrary = oneof [I <$> arbitrary, B <$> arbitrary]
現在替換oneof為frequency每個生成器并將其更改為加權元組:
instance Arbitrary MyData where
arbitrary = frequency [(10, I <$> arbitrary), (1, B <$> arbitrary)]
從這個實體中采樣說明分布現在是傾斜的:
> sample (arbitrary :: Gen MyData)
I 0
I (-2)
I (-4)
I (-1)
I 0
I 8
B True
I 1
I 3
I (-3)
I (-16)
有 10 個I值,只有 1 個B值。
uj5u.com熱心網友回復:
您可以使用generic-random派生它(從1.5.0.0開始)。
Deriving via GenericArbitraryU:給出均勻分布(如oneofMark Seemann 的回答):
{-# Language DataKinds #-}
{-# Language DeriveGeneric #-}
{-# Language DerivingVia #-}
import Test.QuickCheck
import GHC.Generics
import Generic.Random.DerivingVia
-- ghci> :set -XTypeApplications
-- ghci> sample @MyData arbitrary
-- I 0
-- I 1
-- B True
-- I 6
-- I (-5)
-- I (-7)
-- B True
-- I (-10)
-- B True
-- B True
-- I (-9)
data MyData = I Int | B Bool
deriving
stock (Show, Generic)
deriving Arbitrary
via GenericArbitraryU MyData
Deriving via GenericArbitrary: 給出由型別級數字串列指定的加權分布。它們表示每個建構式的頻率(如frequency):
-- ghci> sample @MyData arbitrary
-- I 0
-- I (-2)
-- I 4
-- I 5
-- I 2
-- I 0
-- B False
-- I (-9)
-- I (-10)
-- I (-3)
-- I (-8)
data MyData = I Int | B Bool
deriving
stock (Show, Generic)
deriving Arbitrary
via GenericArbitrary '[10, 1] MyData
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/474026.html
