Oni*_*Oni 12 random haskell types
我已经创建了一种数据类型来包含Rock Paper Scissor游戏中的不同武器.
data Weapon = Rock | Paper | Scissor
Run Code Online (Sandbox Code Playgroud)
现在我想生成一个随机武器,计算机将对用户使用该武器.我看一下我在开头发布的类似链接,但对我来说似乎太笼统了.
我可以从任何其他类型生成随机数.我能理解的是如何使我的数据类型成为Random类的一个实例.
Dan*_*her 14
要生成随机数Weapon,无论您是否创建Weapon实例Random,您需要的是将数字映射到Weapons的方法.如果Enum为类型派生,Int则编译器将定义与s之间的映射.所以你可以定义
randomWeapon :: RandomGen g => g -> (Weapon, g)
randomWeapon g = case randomR (0,2) g of
(r, g') -> (toEnum r, g')
Run Code Online (Sandbox Code Playgroud)
例如.通过Enum实例,您还可以轻松地创建Weapon以下实例Random:
instance Random Weapon where
random g = case randomR (0,2) g of
(r, g') -> (toEnum r, g')
randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of
(r, g') -> (toEnum r, g')
Run Code Online (Sandbox Code Playgroud)
如果有可能从类型中添加或删除构造函数,那么保持randomR与类型同步的边界的最佳方法也是派生出来Bounded,正如Joachim Breitner 立即建议:
data Weapon
= Rock
| Paper
| Scissors
deriving (Bounded, Enum)
instance Random Weapon where
random g = case randomR (fromEnum (minBound :: Weapon), fromEnum (maxBound :: Weapon)) g of
(r, g') -> (toEnum r, g')
randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of
(r, g') -> (toEnum r, g')
Run Code Online (Sandbox Code Playgroud)
虽然Daniel Fischer的Enum方法肯定是一种很好的通用方法,但实际上并没有必要使用Ints 的显式映射.你也可以这样做
instance Random Weapon where
random g = case random g of
(r,g') | r < 1/3 = (Rock , g')
| r < 2/3 = (Paper , g')
| otherwise = (Scissors, g')
Run Code Online (Sandbox Code Playgroud)
使用.的Double实例Random.这比派生Enum实例效率低,但更灵活 - 例如,您可以轻松定义不等分布
random g = case random g of
(r,g') | r < 1/4 = (Rock , g')
| r < 1/2 = (Paper , g')
| otherwise = (Scissors, g')
Run Code Online (Sandbox Code Playgroud)
哪个Scissors比其他两个更可能.当然,如果不等分布在某种程度上对您的数据类型是规范的,那么您应该只做这样的事情,当然不是在这个例子中.
{-# LANGUAGE FlexibleInstances, UndecidableInstances,
ScopedTypeVariables, OverlappingInstances #-}
import System.Random
class (Bounded a, Enum a) => BoundedEnum a
instance (Bounded a, Enum a) => BoundedEnum a
instance BoundedEnum a => Random a where
random gen = randomR (minBound :: a, maxBound :: a) gen
randomR (f, t) gen =
(toEnum r :: a, nextGen)
where
(rnd, nextGen) = next gen
r = fromEnum f + (rnd `mod` length [f..t])
Run Code Online (Sandbox Code Playgroud)
现在你可以说:
r <- randomIO :: Anything
Run Code Online (Sandbox Code Playgroud)
其中任何东西必须是枚举和有界类的实例.
| 归档时间: |
|
| 查看次数: |
3542 次 |
| 最近记录: |