我正在做一个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
答案 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) } ===
.....
一个简单的修复,你就在那里。