Haskell随机数据类型
我是哈斯克尔的新手。 我有一个数据类型:Haskell随机数据类型,haskell,random,Haskell,Random,我是哈斯克尔的新手。 我有一个数据类型: data Sentence= Prop Int | No Sentence | And [Sentence] | Or [Sentence] deriving Eq 我已经为它写了一个展示实例 然而,不管它是否有意义,我希望能够生成一个随机的句子。 如何在Haskell中实现这一点?随机数生成是“不纯”操作的典型示例,因为调用两次随机生成器当然会产生不同的结果-Haskel
data Sentence= Prop Int
| No Sentence
| And [Sentence]
| Or [Sentence]
deriving Eq
我已经为它写了一个展示实例
然而,不管它是否有意义,我希望能够生成一个随机的句子。
如何在Haskell中实现这一点?随机数生成是“不纯”操作的典型示例,因为调用两次随机生成器当然会产生不同的结果-Haskell的本性不允许这样做 因此,您需要使用一个所谓的monad
gena
,它表示一个随机生成器,当运行该生成器时,生成一个a
类型的值
幸运的是,您可以用非常好的语法组合这些生成器
所以,您只需要一些实现这样一个生成器的工具-我们开始吧
randomNo = No <$> randomSentence
randomProp = Prop <$> choose (1, 10)
[...]
randomSentence = oneOf [randomNo, randomProp, ...]
randomNo=无随机语句
randomProp=道具选择(1,10)
[...]
RandomSequence=其中一个[randomNo,randomProp,…]
最简单的方法是使用该模块,它位于随机软件包中,因此您可能必须首先安装它
此模块定义类型类:
class RandomGen g where
next :: g -> (Int,g)
-- ...
class Random r where
random :: RandomGen g => g -> (a,g)
randomR :: RandomGen g => (r,r) -> g -> (a, g)
您必须实现的typeclass是随机的,特定于第一个函数(因为第二个函数没有意义,您可以像randomR=const Random
那样实现。什么是Random
?您得到一个随机生成器作为输入,您必须生成所需的,然后返回新的生成器
要生成随机值,可以使用State
monad,或者类似的方法:
random g = (myResult,gn) where
(random1,g1) = next g
(random2,g2) = next g2
-- ...
-- a type for probability distributions
type Dist = Rand StdGen
-- pick uniformly between a list of values
uniform :: [a] -> Dist a
uniform xs = do
ix <- getRandomR (0, length xs - 1)
return (xs !! ix)
-- return a list of elements generated by the given distribution
randList :: Int -> Dist a -> Dist [a]
randList maxElems dist = do
elems <- getRandomR (0, maxElems)
sequence (replicate elems dist)
-- return a probability distribution of sentences
randSentence :: Dist Sentence
randSentence = do
-- choose one of these four distributions by a uniform distribution
-- (uniform [...] returns a distribution of distributions)
dist <- uniform [
Prop <$> getRandom,
No <$> randSentence,
And <$> randList 5 randSentence,
Or <$> randList 5 randSentence ]
-- and sample the one we chose
dist
然后,您可以通过以下功能使用系统随机生成器:
randomIO :: Random r => IO r
它是预定义的,每次调用都会产生不同的值
然而,最后你必须自己决定如何定义你的随机实例。我最喜欢的方法是使用这个包。虽然它归结起来与传递一些
RandomGen
是一样的,但它可以为你做这件事,并确保你不会在这个过程中搞砸(比如传递一个已经使用过的生成器)此外,randstdgena
对“as的概率分布”有很好的解释
对于您的示例,它可能如下所示:
random g = (myResult,gn) where
(random1,g1) = next g
(random2,g2) = next g2
-- ...
-- a type for probability distributions
type Dist = Rand StdGen
-- pick uniformly between a list of values
uniform :: [a] -> Dist a
uniform xs = do
ix <- getRandomR (0, length xs - 1)
return (xs !! ix)
-- return a list of elements generated by the given distribution
randList :: Int -> Dist a -> Dist [a]
randList maxElems dist = do
elems <- getRandomR (0, maxElems)
sequence (replicate elems dist)
-- return a probability distribution of sentences
randSentence :: Dist Sentence
randSentence = do
-- choose one of these four distributions by a uniform distribution
-- (uniform [...] returns a distribution of distributions)
dist <- uniform [
Prop <$> getRandom,
No <$> randSentence,
And <$> randList 5 randSentence,
Or <$> randList 5 randSentence ]
-- and sample the one we chose
dist
运行任意列表。谢谢您的超快速响应,但您的意思是什么?啊,它来自
控件。Applicative
-只是一些简化的语法,这意味着您可以将函数应用于随机值。啊,好的,但是,当我测试您的代码时,Haskell说:不在范围内:'oneOf',但它应该在Quickcheck中,对吗?是的,您会发现ed Test.QuickCheck和System.Random(Control.Applicative和Control.Monad对于一些额外的功能/语法也非常好)奇怪的是,它能识别导入,但仍然不能识别其中的一个。谢谢!我发现Monad.Random库没有包含在最新的windows软件包中。也许是因为某种原因?从我复制粘贴源代码时开始()在一个自己的文件中,它给了我一些我不知道如何解决的错误:MonadState s(RandT g m)的非法实例声明'您需要通过cabal安装,而不是复制和粘贴。我假设您已经安装了Haskell平台。然后在命令提示下执行cabal安装MonadRandom
。您可能需要先cabal更新
。