1

我正在做一个haskell练习,关于定义一个函数accumulate :: [IO a] -> IO [a],它执行一系列交互并将它们的结果累积到一个列表中。

让我困惑的是如何表达 IO a 的列表?(行动:行动)??

如何使用 IO 编写递归代码?

这是我的代码,但这些存在一些问题......

accumulate :: [IO a] -> IO [a]
accumulate (action:actions) = do 
                                value <- action
                                list <- accumulate (action:actions)
                                return (convert_to_list value list)


convert_to_list:: Num a =>a -> [a]-> [a]
convert_to_list a [] = a:[]
convert_to_list x xs = x:xs
4

4 回答 4

5

您要实现的内容sequence来自Control.Monad.

只是为了让您找到答案而不是给出答案,请尝试[IO a] -> IO [a]hoogle上搜索(当您选择功能时,页面右侧有一个Source链接)。

尝试在您的代码中查看当操作列表为空列表时会发生什么,并查看序列如何处理该问题。

于 2012-09-30T07:20:46.667 回答
2

已经有这样的函数Control.Monad并且它被调用了sequence(不,你不应该看它)。您应该指出在命名过程中做出的重要决定。从技术上讲[IO a],没有说明这些Monads 应该以何种顺序相互连接,但名称sequence具有顺序连接的含​​义。

至于解决你的问题。我建议更多地查看类型并听取@sacundim 的建议。在 GHCi(来自 Glasgow Haskell Compiler 的解释器)中,有一种很好的方法来检查类型并因此理解表达式(:t (:)将返回(:) :: a -> [a] -> [a]它应该提醒您一个自己的函数,但限制较少的类型)。

首先,我会尝试通过更简单的示例查看您所展示的内容。

data MyWrap a = MyWrap a

accumulate :: [MyWrap a] -> MyWrap [a]
accumulate (action:actions) = MyWrap (convert_to_list value values) where
    MyWrap value = action -- use the pattern matching to unwrap value from action
    -- other variant is:
    -- value = case action of
    --             MyWrap x -> x
    MyWrap values = accumulate (action:actions)

我犯了你故意犯的同样的错误,但差别很小(values是一个提示)。正如您可能已经被告知的那样,您可以通过尝试内联适当的函数定义来尝试解释您的任何程序。即匹配等号 ( ) 左侧的定义=并将其替换为右侧。在您的情况下,您有无限循环。尝试在此示例或您的示例上解决它,我想您会理解的(顺便说一句,您的问题可能只是一个错字)。

更新:当您的程序在运行时出现有关模式匹配的消息时,不要害怕。当你把你的函数称为accumulate []

于 2012-09-30T07:20:37.213 回答
1

可能您正在寻找sequence映射的功能[m a] -> m [a]

于 2012-09-30T07:17:56.057 回答
1

因此,您的问题的简短答案是,您的代码(几乎)没有任何问题。

首先,它进行类型检查:

Prelude> let accumulate (action:actions) = do { value <- action ; 
          list <- accumulate (action:actions) ; return (value:list) }
Prelude> :t accumulate
accumulate :: (Monad m) => [m t] -> m [t]

为什么我return (value:list)在那里使用?看看你的第二个功能,它只是(:). 打电话g

g a [] = a:[]
g a xs = a:xs

(:)与使用相同参数调用相同。这就是所谓的“eta 减少”:((\x-> g x) === g===作“等效”)。

所以现在你的代码只剩下一个问题了。您已经value <- action从动作中取出了一个值,那么为什么要在 中重用该动作list <- accumulate (action:actions)?你真的必须吗?现在你有,例如,

accumulate [a,b,c]  ===
do { v1<-a; ls<-accumulate [a,b,c]; return (v1:ls) } ===
do { v1<-a; v2<-a; ls<-accumulate [a,b,c]; return (v1:v2:ls) } ===
do { v1<-a; v2<-a; v3<-a; ls<-accumulate [a,b,c]; return (v1:v2:v3:ls) } ===
.....

一个简单的修复,你就在那里。

于 2012-10-01T02:42:52.637 回答