1

I wrote a program that turned out to be far too slow using lists so I'm trying to switch over to sequences. However, I can't seem to figure out the correct syntax after looking at the documentation.

So far I'm trying to learn with this simple code:

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

I've played around with the syntax for a while with no luck but it still has a ton of errors:

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

I'm new to Haskell so any help would be greatly appreciated!

3
  • How would you do the same thing with lists? Commented Apr 11, 2018 at 13:21
  • Trying to force a Haskell program into the "sequence of statements" model of other languages doesn't usually lead to A Good Place. Commented Apr 11, 2018 at 13:31
  • Your last edit completely changed the question, please don't do that. Commented Apr 11, 2018 at 13:32

1 Answer 1

7

Like almost everything in Haskell, Seq is a purely functional data structure. It's not like an imperative stack where you push stuff to, mutating the original structure. Rather, like ordinary lists, you just generate new container-values which have the extra elements, but this does not affect the old shorter seqs in any way. So, the program you've asked about should just be

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

(It has to be S.lookup, or equivalently S.!?. By itself, lookup is a function that works on plain lists!)

Note that this doesn't really give you any advantage over

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

In fact, lists are usually faster than Seq, they just don't allow efficient random access.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you! This makes sense. I'm getting a not in scope error though, on the S.lookup. I was getting the same in the question code I edited (sorry about that).
Hm, what version of the package are you using? (cabal info containers) lookup has only been added quite recently to the Sequence module (0.5.8), before it had only index, which you can also use (but it doesn't have a safe length-check).
This still feels like an x/y issue. If @Strobe00 desires fast random access/update of elements in an ordered set then they'll probably be better served by a map structure.
@ThomasM.DuBuisson I ended up going with IO Arrays and it's so much faster now.
@Strobe00 though there are use cases where mutable arrays give you better performance than any alternative, I would recommend you only use them as a last-resort optimisation. Many algorithms can be implemented just as efficiently using only purely-functional tools (most I daresay, if you include immutable packed vectors) and only that way do you actually profit from Haskell's great safety guarantees. Using Haskell with mutable arrays is more like writing C with needlessly clunky syntax. Especially, while learning Haskell it makes sense to stick completely to lists to get a feel for it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.