Variables 简单Haskell IORef-“;不能';t匹配类型'IO Int';带有'Int'"E;”can';我看不出是怎么回事';那不一样
我正在尝试在Haskell中使用IORef创建一个简单的随机数生成器来存储可变变量。我的想法是,我可以初始化种子,然后根据种子生成数字,并为下一个随机整数存储新种子 我得到的全部错误是:Variables 简单Haskell IORef-“;不能';t匹配类型'IO Int';带有'Int'"E;”can';我看不出是怎么回事';那不一样,variables,haskell,random,ioref,Variables,Haskell,Random,Ioref,我正在尝试在Haskell中使用IORef创建一个简单的随机数生成器来存储可变变量。我的想法是,我可以初始化种子,然后根据种子生成数字,并为下一个随机整数存储新种子 我得到的全部错误是: random2.hs:9:17: Couldn't match type `IO Int' with `Int' Expected type: IO (IORef Integer) -> (IORef Integer -> IO Int) -&g
random2.hs:9:17:
Couldn't match type `IO Int' with `Int'
Expected type: IO (IORef Integer)
-> (IORef Integer -> IO Int) -> Int
Actual type: IO (IORef Integer)
-> (IORef Integer -> IO Int) -> IO Int
In a stmt of a 'do' block: seed <- newIORef 7
In the expression:
do { seed <- newIORef 7;
randomGen (readIORef seed) }
In an equation for `getRandom':
getRandom
= do { seed <- newIORef 7;
randomGen (readIORef seed) }
random2.hs:10:17:
Couldn't match type `(,) Int' with `IO'
Expected type: IO Int
Actual type: (Int, Int)
In the return type of a call of `randomGen'
In a stmt of a 'do' block: randomGen (readIORef seed)
In the expression:
do { seed <- newIORef 7;
randomGen (readIORef seed) }
random2.hs:10:28:
Couldn't match expected type `Int' with actual type `IO Integer'
In the return type of a call of `readIORef'
In the first argument of `randomGen', namely `(readIORef seed)'
In a stmt of a 'do' block: randomGen (readIORef seed)
Failed, modules loaded: none.
random2.hs:9:17:
无法将类型'IO Int'与'Int'匹配
预期类型:IO(IORef整数)
->(IORef Integer->IO Int)->Int
实际类型:IO(IORef整数)
->(IORef Integer->IO Int)->IO Int
在“do”块的stmt中:种子(Int,Int)
randomGen x=(x,x+1)
getRandom::Int
getRandom=do
种子尝试:
modulemain其中
导入数据.IORef
进口管制
导入数据.Tuple(fst,snd)
randomGen::Int->(Int,Int)
randomGen x=(x,x+1)
getRandom::IO Int->IO(Int,Int)
getRandom x=do
y试试看:
modulemain其中
导入数据.IORef
进口管制
导入数据.Tuple(fst,snd)
randomGen::Int->(Int,Int)
randomGen x=(x,x+1)
getRandom::IO Int->IO(Int,Int)
getRandom x=do
yHaskell中的IO Int
和Int
类型完全不同。这适用于该表单的任何其他类型,如可能是Int
或字符串Int
。这是Haskell类型系统设计的一部分,使其功能强大。你可以把这个表单中的任何东西想象成一种容器,它被参数化了。因此,您可以执行以下操作
getRandom :: IO Int
getRandom = do
seed <- newIORef 7 -- IO (IORef Int)
g <- readIORef seed -- IO Int
let (x, newG) = randomGen g -- (Int, Int)
writeIORef seed newG -- IO ()
return x -- IO Int
getRandom::IO Int
getRandom=do
seedHaskell中的ioint
和Int
类型完全不同。这适用于该表单的任何其他类型,如可能是Int
或字符串Int
。这是Haskell类型系统设计的一部分,使其功能强大。你可以把这个表单中的任何东西想象成一种容器,它被参数化了。因此,您可以执行以下操作
getRandom :: IO Int
getRandom = do
seed <- newIORef 7 -- IO (IORef Int)
g <- readIORef seed -- IO Int
let (x, newG) = randomGen g -- (Int, Int)
writeIORef seed newG -- IO ()
return x -- IO Int
getRandom::IO Int
getRandom=do
seedrandomGen
是纯的,但是readIORef
返回IO a
。您需要在do子句中的randomGen
前面使用liftM
。另外getRandom::IO Int
。一旦它是IO,你就无法摆脱它。@dumb0所以我添加了导入控件。Monad,将getRandom::Int
的定义更改为getRandom::IO Int
,并将最后一行从randomGen(readIORef-seed)
更改为liftM(randomGen(readIORef-seed))
-这就是你刚才描述的吗?因为这会引发另一个错误。我的注释有一个错误:getRandom::IO(Int,Int)
@dumb0仍然是一个错误-无法匹配预期的类型
IO(Int,Int)“实际类型为m0a10->m0r0”
新错误的行数是多少?randomGen
是纯的,但readIORef
返回IO a
。您需要在do子句中的randomGen
前面使用liftM
。另外getRandom::IO Int
。一旦它是IO,你就无法摆脱它。@dumb0所以我添加了导入控件。Monad,将getRandom::Int
的定义更改为getRandom::IO Int
,并将最后一行从randomGen(readIORef-seed)
更改为liftM(randomGen(readIORef-seed))
-这就是你刚才描述的吗?因为这会引发另一个错误。我的评论有一个错误:getRandom::IO(Int,Int)
@dumb0仍然是一个错误-无法将预期的类型
IO(Int,Int)”与实际的类型
m0a10->m0r0'
在什么行号上是新的错误?太棒了,这适用于上述情况。但是因为它现在使用liftM,我不能保存元组中的第二个值,对吗?我想将其保存回IORef,以便下次调用getRandom时返回一个不同的随机数,但这在当前结构中是不可能的?这跟我有什么关系updateIORef@SamHeather您无法避免返回种子并将其传递给下一个调用。getRandom
中的IORef
是函数的局部函数,因此您必须以任何方式返回种子,因此使用IORef
会使生成器变得不纯,而不会为您带来任何好处。如果要使种子传递隐式化,更好的方法是使用状态
monad.@dumb0我不是想重新发明轮子,只是学习。我试图在Haskell中给出一些非常简单的有状态程序的例子(这个),但是即使这个实现看起来也不是有状态的,因为它每次运行时都返回7,从来没有像我希望的那样改变(递增)——我想这是我的误解。你能想出什么办法让它这样做,或者想出一个不同的简单有状态的问题,我可以看看?好吧,我的错。根据我对哈斯克尔有限的经验,没有国家。一旦getRandom返回,就完成了。如果使用相同的值调用getRandom
(例如return4
),则会得到相同的输出。我所做的是创建一个输出,为下次调用getRandom
时提供随机数和种子(例如,(1,4),其中1是随机数,4是再次调用getRandom
时使用的数字)。这在某种意义上模拟了状态。希望这有帮助…太棒了,这对上面的工作。但是因为它现在使用liftM,我不能保存元组中的第二个值,对吗?我想将其保存回IORef,以便下次调用getRandom时返回一个不同的随机数,但这在当前结构中是不可能的?这跟我有什么关系updateIORef@SamHeather您无法避免返回种子并将其传递给下一个调用。getRandom
中的IORef
是函数的局部函数,因此您必须以任何方式返回种子,因此使用IORef
使您的生成器
module Main where
import Data.IORef
import Control.Monad
import Data.Tuple(fst,snd)
randomGen :: Int -> (Int, Int)
randomGen x = (x,x+1)
getRandom :: IO Int -> IO (Int,Int)
getRandom x = do
y <- x
seed <- newIORef y
liftM randomGen $ readIORef seed
getRandom :: IO Int
getRandom = do
seed <- newIORef 7 -- IO (IORef Int)
g <- readIORef seed -- IO Int
let (x, newG) = randomGen g -- (Int, Int)
writeIORef seed newG -- IO ()
return x -- IO Int