简体   繁体   中英

Define a haskell function [IO a] -> IO[a]

I am doing a haskell exercise, regarding define a function accumulate :: [IO a] -> IO [a] which performs a sequence of interactions and accumulates their result in a list.

What makes me confused is how to express a list of IO a ? (action:actions)??

how to write recursive codes using IO??

This is my code, but these exists some problem...

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

What you are trying to implement is sequence from Control.Monad .

Just to let you find the answer instead of giving it, try searching for [IO a] -> IO [a] on hoogle (there's a Source link on the right hand side of the page when you've chosen a function).

Try to see in your code what happens when list of actions is empty list and see what does sequence do to take care of that.

There is already such function in Control.Monad and it called sequence (no you shouldn't look at it). You should denote the important decision taken during naming of it. Technically [IO a] says nothing about in which order those Monad s should be attached to each other, but name sequence puts a meaning of sequential attaching.

As for the solving you problem. I'd suggest to look more at types and took advice of @sacundim. In GHCi (interpreter from Glasgow Haskell Compiler) there is pretty nice way to check type and thus understand expression ( :t (:) will return (:) :: a -> [a] -> [a] which should remind you one of you own function but with less restrictive types).

First of all I'd try to see at what you have showed with more simple example.

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)

I've made the same mistake that you did on purpose but with small difference ( values is a hint). As you probably already have been told you could try to interpret any of you program by trying to inline appropriate functions definitions. Ie match definitions on the left side of equality sign ( = ) and replace it with its right side. In your case you have infinite cycle. Try to solve it on this sample or your and I think you'll understand (btw your problem might be just a typo).

Update: Don't be scary when your program will fall in runtime with message about pattern match. Just think of case when you call your function as accumulate []

可能您正在寻找映射[ma] -> m [a] sequence函数?

So the short version of the answer to your question is, there's (almost) nothing wrong with your code.

First of all, it 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]

Why did I use return (value:list) there? Look at your second function, it's just (:) . Calling g

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

is the same as calling (:) with the same arguments. This is what's known as "eta reduction": (\\x-> gx) === g (read === as "is equivalent").

So now just one problem remains with your code. You've already taken a value value <- action out of the action, so why do you reuse that action in list <- accumulate (action:actions) ? Do you really have to? Right now you have, eg,

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) } ===
.....

One simple fix and you're there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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