在函数中使用时,Haskell中的随机返回类型

在函数中使用时,Haskell中的随机返回类型,haskell,random,types,Haskell,Random,Types,鉴于: 我想举例说明Random,所以我从以下内容开始: import System.Random data Rarity = Common | Uncommon | Rare | Legendary deriving (Show, Eq, Ord, Enum, Bounded) 但是,这是在类型构造函数(私有构造函数)上操作的,而不是类型,所以我认为这是一种根本错误的方法 经过深思熟虑,最终对我起作用的是: randomRarity :: (RandomGen

鉴于:

我想举例说明
Random
,所以我从以下内容开始:

import System.Random

data Rarity = Common | Uncommon | Rare | Legendary
              deriving (Show, Eq, Ord, Enum, Bounded)
但是,这是在类型构造函数(私有构造函数)上操作的,而不是类型,所以我认为这是一种根本错误的方法

经过深思熟虑,最终对我起作用的是:

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')
randomRarity g@(RandomGen t) = case (random g :: (Float, RandomGen t)) of
  ...
randomRarity g=案例随机g
(r,g’| r’<0.50->(普通,g’)
|r'<0.75->(不常见,g')
|r'<0.88->(稀有,g')
|否则->(传奇,g')
其中r'=r::Float
这是相当简洁的,但它声明了另一个变量,它的位置远离它想要影响的东西,这意味着当你看到
r'
时,你必须做双重判断,然后找出它是什么,然后再回来。最糟糕的是,这让我的好奇心没有得到满足。所以我的问题是:


在这个上下文中,有没有一种方法可以告诉
random g
在我调用它时生成一个Float,或者通过正确声明元组中的第二个类型,或者通过某种方式从
g
推断它。或者,如果失败了,有没有一种方法可以约束
r
的类型而不声明另一个变量,如
r'

如果您使用GHC,您可以使用
-XScopedTypeVariables
(或者将
{-#语言范围的TypeVariables#-}
添加到文件的顶部)和代码

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
randomRarity g=案例随机g
(r::Float,g')| r<0.50->(Common,g'))
|r<0.75->(不常见,g')
|r<0.88->(罕见,g')
|否则->(传奇,g')
或者,如果您想使用标准Haskell,您可以使用

randomRarity g = case random g of
      (r::Float,g') | r < 0.50 -> (Common, g')
                    | r < 0.75 -> (Uncommon, g')
                    | r < 0.88 -> (Rare, g')
                    | otherwise -> (Legendary, g')
randorarity g=let(r,g')=random g
如果r::的浮点
r | r<0.50->(普通,g')
|r<0.75->(不常见,g')
|r<0.88->(罕见,g')
|否则->(传奇,g')

我认为在这种情况下,最简单的解决方案是显式键入一个您要比较的数字。这将强制执行
(
randomRarity g = let (r,g') = random g
                 in case r :: Float of
                   r | r < 0.50 -> (Common, g')
                     | r < 0.75 -> (Uncommon, g')
                     | r < 0.88 -> (Rare, g')
                     | otherwise -> (Legendary, g')
randomRarity :: (RandomGen g) => g -> (Rarity, g)
randomRarity g = case random g of
  (r,g') | r < (0.50 :: Float) -> (Common, g')
         | r < 0.75            -> (Uncommon, g')
         | r < 0.88            -> (Rare, g')
         | otherwise           -> (Legendary, g')
randomRarity g = case first (`asTypeOf` (0 :: Float)) $ random g of
    ...
first (`asTypeOf` (0 :: Float)) :: (Float, a) -> (Float, a)