簡體   English   中英

Haskell QuickCheck 在 function 中生成值

[英]Haskell QuickCheck generating values within a function

我如何讓這個人為的例子起作用?

newtype Q = Q [Int]

instance Arbitrary Q where
    arbitrary :: Gen Q
    arbitrary = do
        len <- choose (1, 5)
        pure $ g len (\ i -> i + choose (0, 1)) -- want different choice for each invocation

g :: Int -> (Int -> Int) -> Q -- g is a library function
g len f = Q $ fmap f [1 .. len]

它給出了編譯器錯誤:

    * Couldn't match expected type `Int' with actual type `Gen a0'
    * In the second argument of `(+)', namely `choose (0, 1)'
      In the expression: i + choose (0, 1)
      In the second argument of `g', namely `(\ i -> i + choose (0, 1))'

問題是choose (0, 1)不會產生Int ,它會產生Gen Int

您將其視為此表達式中的Int

pure $ g (\i -> i + choose (0, 1))

由於Gen Int是一個 monad,您需要綁定它才能使用“選擇”的結果。

像這樣的東西:

instance Arbitrary Q where
    arbitrary :: Gen Q
    arbitrary = do
        choice <- choose (0, 1)
        return $ g (\i -> i + choice)

回復已編輯的問題:

問題仍然相同,您嘗試使用Gen Int ,就好像它是Int一樣。 您可以在do內多次綁定。

這是一個解決方案:

instance Arbitrary Q where
    arbitrary :: Gen Q
    arbitrary = do
        len <- choose (1, 5)
        choice <- choose (0, 1)
        return $ g len (\i -> i + choice)

回復已編輯、已編輯的問題

您必須在某處傳播副作用,這僅意味着您需要運行choose len次。 因為g是一個“庫”function,所以我假設您無法控制它,也無法更改它。 請注意,下面的解決方案很難看,因為我需要使用部分 function (!!) ,並且因為它相當慢(可能有更好的方法來做到這一點,但我找不到它)。

這里的訣竅是我正在映射一個返回len Gen Int的 function,然后運行所有這些,生成一個選定數字的列表(有關更多詳細信息,請參見mapM描述)。

instance Arbitrary Q where
 arbitrary :: Gen Q
 arbitrary = do
     len <- choose (1, 5)
     choices <- mapM (\_ -> choose (0, 1)) [1 .. len]
     return $ g len (\i -> i + (choices !! i))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM