繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM