【问题标题】:Working with Data.Sequence in Haskell在 Haskell 中使用 Data.Sequence
【发布时间】:2018-04-11 21:35:46
【问题描述】:

我写了一个程序,结果发现使用列表太慢了,所以我试图切换到序列。但是,在查看文档后,我似乎无法弄清楚正确的语法。

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

import Control.Monad
import qualified Data.Sequence as S

main :: IO ()
main = do 
       let testSeq = S.empty
       testSeq S.|> 5
       testSeq S.|> 20
       testSeq S.|> 3
       let newSeq = S.update 2 3 testSeq
       let x = lookup 2 testSeq
       print x

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

test.hs:9:8:
    Couldn't match expected type ‘IO a0’
                with actual type ‘S.Seq Integer’
    In a stmt of a 'do' block: testSeq S.|> 5
    In the expression:
      do { let testSeq = S.empty;
           testSeq S.|> 5;
           testSeq S.|> 20;
           testSeq S.|> 3;
           .... }
    In an equation for ‘main’:
        main
          = do { let testSeq = ...;
                 testSeq S.|> 5;
                 testSeq S.|> 20;
                 .... }

test.hs:10:8:
    Couldn't match expected type ‘IO a1’
                with actual type ‘S.Seq Integer’
    In a stmt of a 'do' block: testSeq S.|> 20
    In the expression:
      do { let testSeq = S.empty;
           testSeq S.|> 5;
           testSeq S.|> 20;
           testSeq S.|> 3;
           .... }
    In an equation for ‘main’:
        main
          = do { let testSeq = ...;
                 testSeq S.|> 5;
                 testSeq S.|> 20;
                 .... }

test.hs:11:8:
    Couldn't match expected type ‘IO a2’
                with actual type ‘S.Seq Integer’
    In a stmt of a 'do' block: testSeq S.|> 3
    In the expression:
      do { let testSeq = S.empty;
           testSeq S.|> 5;
           testSeq S.|> 20;
           testSeq S.|> 3;
           .... }
    In an equation for ‘main’:
        main
          = do { let testSeq = ...;
                 testSeq S.|> 5;
                 testSeq S.|> 20;
                 .... }

test.hs:13:25:
    Couldn't match expected type ‘[(Integer, b)]’
                with actual type ‘S.Seq a3’
    Relevant bindings include x :: Maybe b (bound at test.hs:13:12)
    In the second argument of ‘lookup’, namely ‘testSeq’
    In the expression: lookup 2 testSeq

我是 Haskell 的新手,非常感谢任何帮助!

【问题讨论】:

  • 你会如何对列表做同样的事情?
  • 试图强制 Haskell 程序进入其他语言的“语句序列”模型通常不会导致 A Good Place。
  • 您上次的编辑完全改变了问题,请不要这样做。

标签: haskell


【解决方案1】:

就像 Haskell 中的几乎所有东西一样,Seq 是一个纯粹的函数式数据结构。它不像一个命令式堆栈,您可以将内容推送到其中,从而改变原始结构。相反,就像普通列表一样,您只需生成具有额外元素的新容器值,但这不会以任何方式影响旧的较短 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

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

请注意,这实际上并没有给您带来任何优势

testSeq = S.update 2 3 $ S.fromList [5,20,30]

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

【讨论】:

  • 谢谢!这是有道理的。不过,在 S.lookup 上,我收到了一个不在范围内的错误。我在编辑的问题代码中得到了相同的结果(对此感到抱歉)。
  • 嗯,你用的是什么版本的包? (cabal info containers) lookup 最近才被添加到 Sequence 模块 (0.5.8),之前它只有 index,您也可以使用它(但它没有安全长度-检查)。
  • 这仍然感觉像是一个 x/y 问题。如果@Strobe00 需要快速随机访问/更新有序集中的元素,那么映射结构可能会更好地为它们提供服务。
  • @ThomasM.DuBuisson 我最终选择了 IO 阵列,现在速度快了很多。
  • @Strobe00 尽管在某些用例中,可变数组比任何替代方案都能为您提供更好的性能,但我建议您仅将它们用作最后​​的优化。许多算法可以仅使用纯功能工具(大多数我敢说,如果你包括不可变的打包向量)同样有效地实现,只有这样你才能真正从 Haskell 的巨大安全保证中受益。将 Haskell 与可变数组一起使用更像是用不必要的笨拙语法编写 C。尤其是在学习 Haskell 时,完全按照列表​​来感受它是很有意义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-12
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多