我需要将IO [Float]
的列表转换为[Float]
。我从以下函数中获得了IO [Float]
对象:
probs :: Int -> IO [Float]
probs 0 = return []
probs n = do
p <- getStdRandom random
ps <- probs (n-1)
return (p:ps)
我知道此函数的结果是类型为[IO Float]的列表,而不是数字列表。它是生成数字的I / O操作的列表。该I / O尚未执行,因此在我的情况下,随机数生成器实际上并未生成数字。我想做的是生成此列表内容的每个随机数,这样我就可以获得一个[Float]
列表。
我需要它来计算结果的每个四分位数中的数量(以检查随机数之间的分布):
calcQuartile :: [Float] -> [Float] -> [Int]
calcQuartile randomList (x1:x2:rest) = length(filter (\x -> x>=x1 && x<x2) randomList):calcQuartile randomList (x2:rest)
calcQuartile x y = []
我使用以下代码运行此功能,该功能不起作用:
calcQuartile (probs x) [0,0.25..1]
我得到的错误是:
• Couldn't match expected type ‘[Float]’
with actual type ‘IO [Float]’
• In the first argument of ‘calcQuartile’, namely ‘(probs x)’
In the expression: calcQuartile (probs x) [0, 0.25 .. 1]
In an equation for ‘getAmountInQuartile’:
getAmountInQuartile x = calcQuartile (probs x) [0, 0.25 .. 1]
答案 0 :(得分:-1)
编辑:正如@freestyle样式所指出的那样,此解决方案有效,但可能导致不可预测的结果:
我导入了模块
System.IO.Unsafe
:import System.IO.Unsafe
接下来,我可以将代码替换为以下内容:
calcQuartile (unsafePerformIO(probs x)) [0,0.25..1]
@Willem Van Onsem指出,更好的解决方案如下:
probs x >>= \y -> return (calcQuartile y [0, 0.25..1])
值得注意的是,尽管它返回IO [Int]
而不是[Int]
。 monadic绑定 >>=
将两个不纯行为(例如IO行为)链接在一起,并从中做出一个IO
行为。同样的事情也可以用do
表示法来写:
do
y <- probs x
return $ calcQuartile y [0, 0.25 .. 1]
在这种情况下,第二个动作(calcQuartile
)实际上是 pure (因此return
,它将纯值包装为无副作用的) IO操作),因此您实际上根本不需要monad实例,而可以仅使用IO
作为函子:
fmap (\y -> calcQuartile y [0, 0.25..1]) $ probs x
或
(`calcQuartile`[0, 0.25..1]) <$> probs x