【发布时间】:2018-06-26 04:40:18
【问题描述】:
我一直试图弄清楚如何在 IO monad 中进行递归。 我熟悉使用纯函数进行递归,但无法将这些知识转移到 IO monads。
纯函数递归
我很乐意使用纯函数进行递归,例如下面的 foo 函数。
foo (x:y:ys) = foo' x y ++ foo ys
带有 IO [String] 输出的函数
我在下面创建了一个类似goo 的函数,它可以满足我的需要并具有 IO 输出。
goo :: String -> String -> IO [String]
goo xs ys = goo' xs ys
试图在 IO monad 中进行递归
当我尝试在 IO monad(例如,“main”函数)中进行递归时,我不能。我查过 liftM、replicateM 和 undo-the-IO <- 运算符或函数。我想要一个像 hoo 或 hoo' 这样的 IO monad(为接下来的胡言乱语道歉)。
hoo :: [String] -> IO [String]
hoo (xs:ys:yss) = do
let rs = goo xs ys ++ hoo yss
return rs
或
hoo' :: [String] -> IO [String]
hoo' (xs:ys:yss) = do
rs <- goo xs ys
let gs = rs ++ hoo' yss
return gs
(顺便说一句,如果您想知道我的项目是什么,我正在为一门课程从头开始编写遗传算法程序。我的 goo 函数需要两个父母并繁殖两个后代,它们作为 IO 返回,因为goo 使用随机数生成器。我需要做的是使用递归 hoo 函数来使用 goo 从 20 个父母的列表中繁殖 20 个后代。我的想法是取前两个列表中的父母,繁殖两个后代,取出列表中接下来的两个父母,再繁殖一对后代,依此类推。)
【问题讨论】:
-
在掌握
(>>=)、(<$>)、liftA2等组合符之前,请确保始终绑定 @987654339 的结果@ 行动。rs <- goo xs ys是正确的,但你必须对hoo'做同样的事情。 -
关于术语的注释:没有“IO monad”这样的东西。
IO(类型)是单子。 -
为了扩展 @melpomene,你所说的 IO monad,我称之为“IO 动作”(= 一个类型为
IO something的值)。 -
为胡言乱语道歉也许尝试一个简单的现实世界问题,例如读取文件并将其内容作为字符串列表返回,会更有效率。
标签: haskell recursion io-monad