我正在根据第一原理在Haskell编程中进行练习。它要求我分别产生相等的概率,以及每个概率分别产生的1 / 3、2 / 3概率:
data Fool =
Fulse
| Frue
deriving (Eq, Show)
我的答案是
module Random where
-- import Test.Hspec
import Test.QuickCheck
data Fool =
Fulse
| Frue
deriving (Eq, Show)
genFool :: Gen Fool
genFool = choose (Fulse, Frue)
genFool' :: Gen Fool
genFool' = do
frequency [(2, return Fulse)
,(1, return Frue)]
但是genFool
是错误的。错误消息是:
../chap14/random.hs:13:11: error:
• No instance for (System.Random.Random Fool)
arising from a use of ‘choose’
• In the expression: choose (Fulse, Frue)
In an equation for ‘genFool’: genFool = choose (Fulse, Frue)
|
13 | genFool = choose (Fulse, Frue)
| ^^^^^^^^^^^^^^^^^^^^
以前我有一些这样的代码:
genBool :: Gen Bool
genBool = choose (False, True)
正常工作。我认为可能需要instance
中的一些预定义System.Random.Random Fool
才能使choose
工作。
我该怎么做才能编译我的genFool
版本?
还有,为什么return Fulse
位于类型genFool'
的第二个Gen Fool
中?
答案 0 :(得分:0)
Test.Quickcheck
模块的choose
函数具有以下类型签名:
choose :: Random a => (a, a) -> Gen a
因此,如果您打算在choose
类型上使用Fool
函数,则必须使其成为Random
类型类的实例,如上面的类型签名所示。
这是定义Random typeclass的地方。它需要randomR
和random
的最小实现。
由于类型Fool
只有两个值,因此它与Bool
类型同构。因此,您可以定义一个适当映射值的函数:
mapBool :: Bool -> Fool
mapBool False = Fulse
mapBool True = Frue
然后您可以为您的类型定义一个typeclass实例:
instance Random Fool where
random g = let (b :: Bool, g') = random g
in (mapBool b, g')
randomR _ g = (random g) -- Note that this doesn't work correctly. You need to pattern match and fix this.
上面的代码应该可以使您的模块正常编译。