考虑:返回类型
import System.Random
data Rarity = Common | Uncommon | Rare | Legendary
deriving (Show, Eq, Ord, Enum, Bounded)
我想实例Random
,所以我开始了类似:
randomRarity :: (RandomGen g) => g -> (Rarity, g)
randomRarity g = case random g of
(r,g') | r < 0.50 -> (Common, g')
| r < 0.75 -> (Uncommon, g')
| r < 0.88 -> (Rare, g')
| otherwise -> (Legendary, g')
,但是这虽然失败,因为即使它知道它需要从所有比较随机Ord
,它不能告诉我真正想要的是一个随机Float
。因此,我认为我需要键入的random g
的返回值,但我遇到了一个问题:
(random g :: (Float, ???))
因为它是一个元组,我该怎么申报为第二类型?我尝试了类似(random g :: (Float, RandomGen t))
,但不能推断出t
,我不知道如何将它与g
的类型相匹配。我得到它通过使用StdGen
到处工作,而不是RandomGen g
,但后来我不能实例Random
,它可能应该与任何随机RandomGen
,无论如何应用。说实话,我甚至不在乎它是什么,因为我只是把它传递开来,但感觉就像我被迫。我试图做找出正确的类型如下:
randomRarity [email protected](RandomGen t) = case (random g :: (Float, RandomGen t)) of
...
但操作上类型构造(私人的,不会少),不类型,所以我认为这是一个根本错误的做法。
推理一下后,终于为我工作的事情是以下几点:
randomRarity g = case random g of
(r,g') | r' < 0.50 -> (Common, g')
| r' < 0.75 -> (Uncommon, g')
| r' < 0.88 -> (Rare, g')
| otherwise -> (Legendary, g')
where r' = r :: Float
这是相当简洁,但它宣称多数民众赞成远离其意在影响事情的另一个变量,这意味着当你看到r'
时,你必须做一个双重处理,然后去弄清它是什么,然后回来。最糟糕的是,这让我的好奇心得不到满足。所以我的问题是:
在这种情况下,有一种方法可以告诉random g
在我通过正确声明元组中的第二个类型来调用它时生成一个Float,或者以某种方式从g
推断它。或者,如果失败了,是否有一种方法可以在不声明r'
之类的其他变量的情况下约束r
的类型?