在 Haskell 中使用 Data.Sequence

Str*_*e00 1 haskell

我编写了一个程序,结果使用列表太慢了,所以我尝试切换到序列。但是,在查看文档后我似乎无法找出正确的语法。

\n\n

到目前为止,我正在尝试使用这个简单的代码来学习:

\n\n
import Control.Monad\nimport qualified Data.Sequence as S\n\nmain :: IO ()\nmain = do \n       let testSeq = S.empty\n       testSeq S.|> 5\n       testSeq S.|> 20\n       testSeq S.|> 3\n       let newSeq = S.update 2 3 testSeq\n       let x = lookup 2 testSeq\n       print x\n
Run Code Online (Sandbox Code Playgroud)\n\n

我已经尝试了一段时间的语法但没有运气,但它仍然有很多错误:

\n\n
test.hs:9:8:\n    Couldn't match expected type \xe2\x80\x98IO a0\xe2\x80\x99\n                with actual type \xe2\x80\x98S.Seq Integer\xe2\x80\x99\n    In a stmt of a 'do' block: testSeq S.|> 5\n    In the expression:\n      do { let testSeq = S.empty;\n           testSeq S.|> 5;\n           testSeq S.|> 20;\n           testSeq S.|> 3;\n           .... }\n    In an equation for \xe2\x80\x98main\xe2\x80\x99:\n        main\n          = do { let testSeq = ...;\n                 testSeq S.|> 5;\n                 testSeq S.|> 20;\n                 .... }\n\ntest.hs:10:8:\n    Couldn't match expected type \xe2\x80\x98IO a1\xe2\x80\x99\n                with actual type \xe2\x80\x98S.Seq Integer\xe2\x80\x99\n    In a stmt of a 'do' block: testSeq S.|> 20\n    In the expression:\n      do { let testSeq = S.empty;\n           testSeq S.|> 5;\n           testSeq S.|> 20;\n           testSeq S.|> 3;\n           .... }\n    In an equation for \xe2\x80\x98main\xe2\x80\x99:\n        main\n          = do { let testSeq = ...;\n                 testSeq S.|> 5;\n                 testSeq S.|> 20;\n                 .... }\n\ntest.hs:11:8:\n    Couldn't match expected type \xe2\x80\x98IO a2\xe2\x80\x99\n                with actual type \xe2\x80\x98S.Seq Integer\xe2\x80\x99\n    In a stmt of a 'do' block: testSeq S.|> 3\n    In the expression:\n      do { let testSeq = S.empty;\n           testSeq S.|> 5;\n           testSeq S.|> 20;\n           testSeq S.|> 3;\n           .... }\n    In an equation for \xe2\x80\x98main\xe2\x80\x99:\n        main\n          = do { let testSeq = ...;\n                 testSeq S.|> 5;\n                 testSeq S.|> 20;\n                 .... }\n\ntest.hs:13:25:\n    Couldn't match expected type \xe2\x80\x98[(Integer, b)]\xe2\x80\x99\n                with actual type \xe2\x80\x98S.Seq a3\xe2\x80\x99\n    Relevant bindings include x :: Maybe b (bound at test.hs:13:12)\n    In the second argument of \xe2\x80\x98lookup\xe2\x80\x99, namely \xe2\x80\x98testSeq\xe2\x80\x99\n    In the expression: lookup 2 testSeq\n
Run Code Online (Sandbox Code Playgroud)\n\n

我是 Haskell 的新手,因此我们将不胜感激!

\n

lef*_*out 7

就像 Haskell 中的几乎所有内容一样,Seq它是一个纯函数式数据结构。它不像命令式堆栈,您可以将内容推入其中,从而改变原始结构。相反,像普通列表一样,您只需生成具有额外元素的新容器值,但这不会以任何方式影响旧的较短序列。所以,你问的程序应该是

testSeq :: S.Seq Int
testSeq = S.update 2 3 $ S.empty S.|> 5 S.|> 20 S.|> 30

main :: IO ()
main = print $ S.lookup 2 testSeq
Run Code Online (Sandbox Code Playgroud)

(它必须是S.lookup,或者等效地S.!?。它本身lookup就是一个适用于普通列表的函数!)

请注意,这并没有真正给你带来任何优势

testSeq = S.update 2 3 $ S.fromList [5,20,30]
Run Code Online (Sandbox Code Playgroud)

事实上,列表通常比更快Seq,它们只是不允许有效的随机访问。

  • 嗯,您使用的是哪个版本的软件包?(`cabal info strings`) `lookup` 最近才被添加到 `Sequence` 模块 (0.5.8),之前它只有 [`index`](http://hackage.haskell.org/package/ Containers-0.5.7.0/docs/Data-Sequence.html#v:index),您也可以使用它(但它没有安全的长度检查)。 (3认同)