[英]Define a haskell function [IO a] -> IO[a]
我正在做一次haskell练习,关于定义一个函数accumise :: [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
您要实现的是Control.Monad
sequence
。
只是为了让你找到答案,而不是给它,尝试搜索[IO a] -> IO [a]
上hoogle (有,当你选择了一个功能页面的右手边源链接)。
尝试在代码中查看当动作列表为空列表时会发生什么,并查看序列做了什么来解决这一问题。
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 []
时,请考虑一下情况
可能您正在寻找映射[ma] -> m [a]
sequence
函数?
因此,对于您的问题的答案的简短版本是,您的代码几乎没有错误。
首先,它进行类型检查:
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-> gx) === 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) } ===
.....
一个简单的修复程序,您就在那里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.