在Haskell中将IO [Float]转换为[Float]

时间:2018-09-13 08:43:26

标签: haskell casting io

我需要将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]

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