haskell : "instance (Enum a, Bounded a) => Random a"和 "=> Arbitrary a"

标签 haskell random

在 Haskell,是否有用于生成 Random 的“标准”库/包?/Arbitrary枚举?

我编写了以下代码,但我不敢相信我是第一个有这种需求或解决它的人(而且我不确定我的解决方案是否完全正确)。
另外,我希望现有的解决方案具有其他不错的功能。

这是一对从 Enum 类型中选择随机值的函数:

enumRandomR :: (RandomGen g, Enum e) => (e, e) -> g -> (e, g)
enumRandomR  (lo,hi) gen = 
    let (int, gen') = randomR (fromEnum lo, fromEnum hi) gen in (toEnum int, gen')

enumRandom  :: (RandomGen g, Enum e) => g -> (e, g)
enumRandom gen = 
    let (int, gen') = random gen in (toEnum int, gen')

这里是 System.Random.Random 的实例和 Test.QuickCheck.Arbitrary
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}

instance (Enum a, Bounded a) => Random a where
   random = enumRandom
   randomR = enumRandomR

instance (Enum a, Bounded a) => Arbitrary a where
  arbitrary = choose (minBound, maxBound)

这是一个示例 Bounded , Enum类型
data Dir = N | E | S | W
   deriving (Show, Enum, Bounded)

这是随机/任意方法的测试
> import Test.QuickCheck
> sample (arbitrary:: Gen Dir)
N
E
N
S
N
E
W
N
N
W
W

我不高兴我的解决方案依赖于这些扩展:
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}"

因为:
- Constraint is no smaller than the instance head
  in the constraint: Enum a
(Use -XUndecidableInstances to permit this)

,
- Overlapping instances for Random Int
  arising from a use of `randomR'
Matching instances:
  instance Random Int -- Defined in System.Random
  instance (Enum a, Bounded a) => Random a

, 和
- Illegal instance declaration for `Random a'
  (All instance types must be of the form (T a1 ... an)
   where a1 ... an are *distinct type variables*,
   and each type variable appears at most once in the instance head.
   Use -XFlexibleInstances if you want to disable this.)

有没有更好的办法?我的解决方案对于某些(更“异国情调”)有界枚举类型是否比我的简单示例失败?

最佳答案

在这种情况下的标准解决方法是创建一个 newtype包装器并为此提供实例。

{-# LANGUAGE GeneralizedNewtypeDeriving #-}  -- avoid some boilerplate

newtype Enum' a = Enum' a
  deriving (Bounded, Enum, Show)

instance (Enum a, Bounded a) => Random (Enum' a) where
  random = enumRandom
  randomR = enumRandomR

instance (Enum a, Bounded a) => Arbitrary (Enum' a) where
  arbitrary = choose (minBound, maxBound)

当然,这种方法在使用新类型时需要一些额外的包装和展开,但是对于 QuickCheck 使用,这应该不会太糟糕,因为您通常只需要对每个属性进行一次模式匹配:
prop_foo (Enum' x) = ... -- use x as before here

关于 haskell : "instance (Enum a, Bounded a) => Random a"和 "=> Arbitrary a",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9188409/

相关文章:

haskell - Haskell 是否支持类型类的匿名实例?

haskell - 什么是 Cabal 组件以及如何使用它们?

haskell - Haskell 中的绑定(bind)是什么意思?

C++ rand () 没有提供基于种子的正确数字

java - 如何执行 JButton Action 监听器一定次数

c - 生成一个长度为25的随机数

haskell - 与分数相关的类型错误

algorithm - 你会如何在 Haskell 中表达它?

c++ - c++中的替换密码

c# - 选择 WPF 随机画笔颜色