从Haskell中的intMap中获取一个随机值

从Haskell中的intMap中获取一个随机值,haskell,random,Haskell,Random,我在编写模拟掷骰子的函数时遇到了一些问题。 所说的骰子有6条边,上面有1-5和W。 1得1分,2得2分,依此类推。但W值5分。 我制作了一个数据类型端,带有一个Char值和一个Int points。我生成一个intMap,保存所有六个边,然后使用函数rollDice,它应该返回一个随机边 像这样: module Dice where import qualified Data.IntMap as IM import System.Random data Side = Side {

我在编写模拟掷骰子的函数时遇到了一些问题。 所说的骰子有6条边,上面有1-5和W。 1得1分,2得2分,依此类推。但W值5分。 我制作了一个数据类型端,带有一个Char值和一个Int points。我生成一个intMap,保存所有六个边,然后使用函数rollDice,它应该返回一个随机边

像这样:

module Dice where

import qualified Data.IntMap as IM
import System.Random


data Side = Side {
            value :: Char, 
            points :: Int
            } deriving Show



data Dice = Dice (IM.IntMap (Side))

dice = Dice $ IM.fromList[(0,Side '1' 1),(1,Side '2' 2),
                                        (2 ,Side '3' 3),(3,Side '4' 4),
                                        (4,Side '5' 5),(5,Side 'W' 5)]



throwDice :: Dice -> Side
throwDice (Dice (intMap)) = intMap IM.!(randomRIO (1,6 :: Int))
尝试加载时返回以下错误:

Dice.hs:22:41:
    Couldn't match expected type `IM.Key' with actual type `IO a0'
    In the return type of a call of `randomRIO'
    In the second argument of `(IM.!)', namely
      `(randomRIO (1, 6 :: Int))'
    In the expression: intMap IM.! (randomRIO (1, 6 :: Int))
我在某个地方读到过,您应该只在IO monad中使用RandomRIO,但我需要将抛出的端附加到列表中,然后显示该列表中所有端的值,我完全不知道如何将RandomRIO函数的输出转换为可用的格式


提前感谢。

randomRIO
具有类型
Random a=>(a,a)->IO a
,这意味着结果值被捕获到IO monad。IO monad无法转义,因此如果要使用随机值,函数也必须返回IO绑定类型的值(如果相同的输入不能产生相同的输出,函数就不能是纯的)

我希望是这样

import Control.Monad (replicateM)
import System.Random 

main = do
    randList <- replicateM yourListSize (randomRIO (1,6))
    print randList
import Control.Monad(复制项)
导入系统。随机
main=do

randList是的,在IO monad中编程可能会让新手感到沮丧,但没有出路。你可以使用另一个单子,比如State,但它仍然是你必须处理的单子。这不是限制,纯函数不可能是非确定性的,这是自然和正确的。有
unsafePerformIO
可以帮助你愚弄编译器,但在这种情况下使用它肯定会把程序搞砸。
unsafePerformIO
不是为了“愚弄编译器”@CatPlusPlus它无论如何都不适合这种情况。您有键
0,1,2,3,4,5
。在这种情况下,查找表的适当数据结构是数组。(注意:您的查找假设键从1到6,两个键中的一个应该调整。)您应该将获取随机索引与表中的查找分开。为了知道正确的方法是什么,我们需要知道你实际上在做什么。使用
randomRIO
几乎总是一个错误。