haskell - 在 Haskell 中将 IO [Float] 转换为 [Float]
问题描述
我需要将列表转换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]
解决方案
编辑:正如@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])
值得注意的是,这将返回 aIO [Int]
而不是 a [Int]
。monadic绑定 >>=
将两个不纯的动作链接在一起(即在本例中为 IO 动作)并从它们中生成单个IO
动作。同样的事情也可以用do
符号来写:
do
y <- probs x
return $ calcQuartile y [0, 0.25 .. 1]
在这种特殊情况下,第二个动作( the calcQuartile
)实际上是纯的(因此 the return
,它将纯值包装为无副作用的 IO 动作),因此您根本不需要 monad 实例,而只需用作IO
函子:
fmap (\y -> calcQuartile y [0, 0.25..1]) $ probs x
或者
(`calcQuartile`[0, 0.25..1]) <$> probs x
推荐阅读
- javascript - 基于 vue-route-link active 的动态颜色
- azure - 在 Azure 托管的多容器 Web 应用程序中,无法连接到 unix:///var/run/docker.sock 上的 Docker 守护程序
- python - 上传到 GitHub 的 Jupyter notebook 不显示folium map
- assembly - 大会 AT&T:movq %rdi, %rdx?
- java - 无法解决关闭 preparesStatement 的 SonarQube 错误
- ios - 无效的 `Podfile` 文件:无法加载此类文件 -- path/to/.ios/Flutter/podhelper.rb
- powerbi - Power Bi 排序日期表
- html - 用 svg 中的透明路径重叠彩色矩形/在与路径的交叉点上破坏矩形填充颜色
- go - 如何解压单个文件?
- regex - 需要删除删除正则表达式中的模式/字符串(记事本++)