2017-04-22 133 views
1

我有这样的功能:IO序列哈斯克尔

sequence :: [IO a] -> IO [a] 
sequence [] = pure [] 
sequence (op:ops) = do 
    x <- op 
    xs <- sequence ops 
    return (x:xs) 

刚刚写入的IO操作的顺序。

问题是我想编写相同的函数,但是完全不使用'do notation',只是使用操作符>>和>> =来代替。

我已经有该版本:

mySequence:: [IO a]-> IO [a] 
mySequence [] = pure [] 
mySequence (op:ops) = 
    op >> sequence ops 

但它不会例如与输入[纯1,纯2]工作。

任何人都可以帮助我吗?

在此先感谢。

+0

在'do'版本中,您有2个绑定和一个return语句。在没有'do'的版本中,你使用'>>',它放弃了它左边的操作数的结果,并且你唯一返回的是'[]'。 'do'版本也使用':'运算符,而''''''''''版本不支持。 – sepp2k

回答

1

在应用性的符号,这是相当简单:

sequence (op:ops) = (:) <$> op <*> sequence ops 

林单子符号,只是翻译do,同时保持其结构:

sequence (op:ops) = 
    op    >>= \x -> 
    sequence ops >>= \xs -> 
    return (x:xs) 

粗略地说,x <- action; ...变得action >>= \x -> ...。请注意,上述lambda表达式的范围一直延伸到表达式的最后。使用明确的括号:

sequence (op:ops) = 
    op >>= (\x -> sequence ops >>= (\xs -> return (x:xs))) 
+0

感谢您的回答。 如果我们调用如下函数:sequence [putStr“hi”,pure 4], 这不起作用,为什么? –

+1

@AntonioSerrano什么是'[putStr“hi”,纯4]'的类型? 'putStr“hi”'和'pure 4'具有不兼容的类型,你不能把它们放在同一个列表中(除非你创建了一个'instance Num()',我想)。 – sepp2k

+0

好的,我明白了,但为什么以[纯1,纯2]为例仍然不起作用? @ sepp2k –