Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move an element in a list in Haskell?

Tags:

list

haskell

I'm reading through Learn You a Haskell and reached a spot where I'm trying to move an element in a list to the head. I've come up with what I think is the naive way and I'm curious if someone can show me what the experienced Haskell programmer would do instead.

In this example, I have a list of Integers and I want to move the element '4', which would be index '3', to the head of the list.

let nums = [1, 2, 3, 4, 5]
(nums !! 3) : delete (nums !! 3) nums

returns [4, 1, 2, 3, 5].

What do you think?

like image 827
afrosteve Avatar asked Jun 24 '09 23:06

afrosteve


2 Answers

I would do it this way:

move n as = head ts : (hs ++ tail ts)
   where (hs, ts) = splitAt n as

splitAt splits a list at the given position, it returns the two parts that are created by the splitting (here hs and ts). The element that should be moved to the front is now at the beginning of ts. head ts returns just this first element of ts, tail ts returns everything but that first element. The result of the function are just these parts combined in the right order: hs concatenated with tail ts and prepended by the element head ts.

like image 126
sth Avatar answered Oct 07 '22 03:10

sth


Experienced Haskellers hardly ever using list indexing. I'd use break to avoid repeated traversals (assuming you want to match on element '4', not index '3'):

case break (== 4)  [1, 2, 3, 4, 5] of
    (a,x:xs) -> x:a ++ xs
    (a,xs)    -> a ++ xs

As in:

Prelude Data.List> case break (== 4)  [1, 2, 3, 4, 5] of (a,x:xs) -> x:a ++ xs; (a,xs) -> a ++ xs
[4,1,2,3,5]

We can do the same with indexing via 'splitAt':

Prelude Data.List> case splitAt 3  [1, 2, 3, 4, 5] of (a,x:xs) -> x:a ++ xs; (a,xs) -> a ++ xs
[4,1,2,3,5]
like image 25
Don Stewart Avatar answered Oct 07 '22 03:10

Don Stewart