定义haskell函数[IO a] - > IO并[a]

时间:2012-09-30 06:04:24

标签: haskell recursion io

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

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

如何使用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 个答案:

答案 0 :(得分:5)

您尝试实施的内容是来自sequence的{​​{1}}。

只是为了让您找到答案而非提供答案,尝试在hoogle上搜索Control.Monad(页面右侧有一个来源链接你选择了一个功能。)

尝试在代码中查看当操作列表为空列表时会发生什么,并查看序列执行哪些操作。

答案 1 :(得分:2)

Control.Monad中已经存在这样的功能,它称为sequence(不,你不应该看它)。您应该表示在命名期间做出的重要决定。从技术上讲,[IO a]没有说明Monad应该相互依附的顺序,但名称sequence表示顺序附加的含义。

至于解决你的问题。我建议多看一下类型并听取@sacundim的建议。在GHCi(格拉斯哥Haskell编译器的解释器)中,有一种非常好的方法来检查类型,从而理解表达式(: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 []

,只需考虑一下

答案 2 :(得分:1)

您可能正在寻找映射sequence的{​​{1}}函数吗?

答案 3 :(得分:1)

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

首先,它是typechecks:

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 reduction”:(\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) } ===
.....

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