对于Haskell来说我很新。 我有一个数据类型:Haskell从数据类型中随机输入
data Sentence= Prop Int
| No Sentence
| And [Sentence]
| Or [Sentence]
deriving Eq
我已经写了一个显示实例它
然而,是否有意义或不,我希望能够生成一个随机的句子。 我如何在Haskell中完成此任务?
对于Haskell来说我很新。 我有一个数据类型:Haskell从数据类型中随机输入
data Sentence= Prop Int
| No Sentence
| And [Sentence]
| Or [Sentence]
deriving Eq
我已经写了一个显示实例它
然而,是否有意义或不,我希望能够生成一个随机的句子。 我如何在Haskell中完成此任务?
随机数生成是“不纯”操作的典型示例,因为调用一个随机生成器两次当然会产生不同的结果 - Haskell的本性不允许这样做。
因此,你需要使用所谓的单子Gen a
代表一个随机生成,即在运行时产生a
类型的值。
幸运的是,你可以在一个相当不错的语法结合这些发电机...
所以,你只需要一些library实现这种发电机 - 在这里,我们走了。
randomNo = No <$> randomSentence
randomProp = Prop <$> choose (1, 10)
[...]
randomSentence = oneOf [randomNo, randomProp, ...]
最简单的方法是使用模块System.Random
,它在随机包装,所以你可能需要先安装它。
这个模块定义了类型类:
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)
的类型类,你必须实现是随机的,具体的第一功能(作为第二是没有意义的,你可以实现像randomR = const random
什么random
?你得到一个随机生成的输入,必须生成您所需要的它,并赋予新的发电机回
要生成的随机值,你既可以使用State
单子,或者是这样的:。
random g = (myResult,gn) where
(random1,g1) = next g
(random2,g2) = next g2
-- ...
然后,您可以通过此功能使用的系统随机生成:
randomIO :: Random r => IO r
它是预定义的,会产生不同的值,每次调用。
但是,最后你必须决定如何定义你的Random实例。
我最喜欢的方法是使用MonadRandom包。虽然它归结为与传递一些RandomGen
一样的东西,但它可以帮助您,并确保您不会在流程中搞砸(例如传递已使用的生成器)。此外,Rand StdGen a
对“a
s的概率分布”有很好的解释。
对于你的榜样,它可能是这样的:
-- 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
注神奇的数字5在那里。那是因为我们没有得到20亿个元素列表。您可能需要调整随机生成列表中术语数量的分布。
并运行它,你可以使用evalRandIO
或许多其他的东西,说这样的:
main = print =<< evalRandIO randSentence
谢谢! 我发现Monad.Random库不包含在最新的Windows软件包中。也许是有原因的?因为当我从它复制粘贴来源(http://www.haskell.org/haskellwiki/NewMonads/MonadRandom)到一个自己的文件时,它会给我错误,我不知道如何解决它:非法实例声明对于'MonadState s(RandT gm)' – SirLenz0rlot 2010-09-23 07:56:19
您需要通过cabal进行安装,而不是复制和粘贴。我假设你已经安装了Haskell平台。然后在命令提示符下执行'cabal install MonadRandom'。您可能需要先“更新cabal”。 – luqui 2010-09-23 16:25:55
pick :: [a] -> IO a
pick xs = randomRIO (0, length xs - 1) >>= return . (xs !!)
运行挑过任何名单。
感谢您的超快反应,但是您的意思是<$>? – SirLenz0rlot 2010-09-22 12:46:20
啊,它来自'Control.Applicative' - 只是一些简化的语法,这意味着您可以将函数应用于随机值。 – Dario 2010-09-22 12:47:55
这只是'fmap' – fuz 2010-09-22 12:49:15