考慮:返回類型
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
的類型?