I execute this statement on the interpreter
foldr (\x (a, b) -> if x == '_' then (a+1, [((div a 3), (mod a 3))] ++ b) else (a, b)) (0, []) "_______OX"
I expected the output to be
(7,[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2.0)])
however the output is
(7,[(2,0),(1,2),(1,1),(1,0),(0,2),(0,1),(0,0)])
what am I doing wrong. As far as I know, foldr starts from the last element of the list and my lambda function appends it to the beginning of the accumulator list. So I should get (0,0) as the first element. However, it's the opposite and I'm puzzled. :(
Also, a small question - How do I go about assigning tags for questions like these?
After 'X' you have
(0,[])
After '0' you have
(0,[])
After first '_' you have
(1,[(0,0)])
After secont '_' you have
(2,[(0,1),(0,0)]) -- you prepend in: [((div a 3), (mod a 3))] ++ b
After third '_' you have
(3,[(O,2),(0,1),(0,0)])
...
Let's simplify this a bit, for better explanation:
foldr (\c (a,b) -> (a+1, a:b)) (0, []) "hi"
Foldr is defined as
foldr f a [] = a
foldr f a (x:xs) = f x (foldr f a xs)
Let us call the lambda function g
Hence, the trace of the expression above:
g 'h' (foldr g (0,[]) "i")
g 'h' (g 'i' (foldr g (0,[]) ""))
g 'h' (g 'i' (0, []))
g 'h' (1, [0])
(2, [1,0])
Related
There is some case where I don't understand how foldr and foldl are used in function.
Here is a couple of example, I then explain why I don't understand them:
-- Two implementation of filter and map
map' f = foldr (\x acc -> (f x):acc) []
map'' f xs = foldl (\acc x -> acc ++ [(f x)]) [] xs
filter' f xs = foldr(\x acc -> if(f x) then x:acc else acc) [] xs
filter'' f = foldl(\acc x -> if(f x) then acc++[x] else acc) []
Why does map'' makes the use of xs but non map'? Shouldn't map' need a list for the list comprehension formula as well?
Same case for filter' vs filter''.
Here is an implementation which insert elements in a sorted sequence:
insert e [] = [e]
insert e (x:xs)
| e > x = x: insert e xs
| otherwise = e:x:xs
sortInsertion xs = foldr insert [] xs
sortInsertion'' xs = foldl (flip insert) [] xs
Why are the argument for insert flipped in sortInsertion ([] xs) (empty list and list) compare to the definition of insert(e []) (element and empty list)
Why does map'' makes the use of xs but non map'? Shouldn't map' need a list for the list comprehension formula as well? Same case for filter' vs filter''.
This is called “eta-reduction” and it’s a common way of omitting redundant parameter names (“point-free style”). Essentially whenever you have a function whose body is just an application of a function to its argument, you can reduce away the argument:
add :: Int -> Int -> Int
add x y = x + y
-- “To add x and y, call (+) on x and y.”
add :: (Int) -> (Int) -> (Int)
add x y = ((+) x) y
-- “To add x, call (+) on x.”
add :: (Int) -> (Int -> Int)
add x = (+) x
-- “To add, call (+).”
add :: (Int -> Int -> Int)
add = (+)
More precisely, if you have f x = g x where x does not appear in g, then you can write f = g.
A common mistake is then wondering why f x = g . h x can’t be written as f = g . h. It doesn’t fit the pattern because the (.) operator is the top-level expression in the body of f: it’s actually f x = (.) g (h x). You can write this as f x = (((.) g) . h) x and then reduce it to f = (.) g . h or f = fmap g . h using the Functor instance for ->, but this isn’t considered very readable.
Why are the argument for insert flipped in sortInsertion
The functional parameters of foldr and foldl have different argument order:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
Or, with more verbose type variable names:
foldr
:: (Foldable container)
=> (element -> accumulator -> accumulator)
-> accumulator -> container element -> accumulator
foldl
:: (Foldable container)
=> (accumulator -> element -> accumulator)
-> accumulator -> container element -> accumulator
This is just a mnemonic for the direction that the fold associates:
foldr f z [a, b, c, d]
==
f a (f b (f c (f d z))) -- accumulator on the right (second argument)
foldl f z [a, b, c, d]
==
f (f (f (f z a) b) c) d -- accumulator on the left (first argument)
That is partial function application.
map' f = foldr (\x acc -> (f x):acc) []
is just the same as
map' f xs = foldr (\x acc -> (f x):acc) [] xs
if you omit xs on both sides.
However, beside this explanation, I think you need a beginner book for Haskell. Consider LYAH.
I have the following type:
newtype Rep f a = Rep { runRep :: String -> f (String, a) }
The type Rep f a is a stateful computation that takes a String as the initial state and produces a (String, a) as the result of the computation. The result of the computation is wrapped in the functor f.
The Applicative instance for Rep is the following:
instance Monad f => Applicative (Rep f) where
pure x = Rep $ \s -> pure (s, x)
Rep f <*> Rep x = Rep $ \s -> do
(s',rf) <- f s
(s'',rx) <- x s'
return (s'', rf rx)
And the Monad instance for Rep is the following:
instance Monad f => Monad (Rep f) where
return x = pure x
Rep a >>= f = Rep $ \s -> do
(s', ya) <- a s
let (Rep f') = f ya
(s'', yf) <- f' s'
pure (s'', yf)
The Alternative instance for Rep is the following:
instance (Monad f, Alternative f) => Alternative (Rep f) where
empty = Rep (const empty)
Rep a <|> Rep b = Rep $ \s -> a s <|> b s
I have the following data types and function:
data TD = Empty | Fol TD TD | Letters [Char] | Str TD
data Res = Nil | Character Char | Cop Res Res | Special [Res]
findmatch :: (Monad f, Alternative f) => TD -> Rep f Res
findmatch (Str a) =
frontAdd <$> findmatch a <*> findmatch (Str a)
<|> pure (Special [])
where
frontAdd x (Special xs) = Special (x:xs)
frontAdd _ _ = error "Not possible."
I am having trouble understanding the function above. The function frontAdd creates a Special value which contains a list of [Res]. findmatch returns Rep f Res. The line frontAdd <$> findmatch a <*> findmatch (Str a) applies frontAdd to the Res that is returned by findmatch a and findmatch (Str a).
However, I am not sure how this line, with the pattern matching, works: frontAdd x (Special xs) = Special (x:xs). Further, assuming that the functor f is [ ], how would the <|> in frontAdd <$> findmatch a <*> findmatch (Str a) <|> pure (Special []) work? I know that if the functor f is Maybe, then <|> makes a left-biased choice, but I don't know how <|> works specifically for lists. In the documentation it states:
instance Alternative [] where
empty = []
(<|>) = (++) -- length xs + length ys = length (xs ++ ys)
How exactly does the concatenation work? Am I correct in saying that the result of frontAdd <$> findmatch a <*> findmatch (Str a) is concatenated with the empty list?
Any insights are appreciated.
First, if f is [], then pure (Special []) is [(Special [])], which is just [Special []].
Second, list concatenation is the most natural thing, with
[a, b, c, d, ...] ++ [p, q, r, s, ...]
==
[a, b, c, d, ... , p, q, r, s, ...]
i.e.
(x:xs) ++ ys = x : (xs ++ ys)
[] ++ ys = ys
which is to say,
xs ++ ys = foldr (:) ys xs
Thus
[a, b, c] <|> [Special []]
==
[a, b, c, Special []]
and
[] <|> [Special []]
==
[ Special []]
So no, <|> pure (Special []) does not concatenate with the empty list, but rather with a list of a Special wrapping the empty list.
So, I am given a list containing tuples and I need to break it down into two lists, the first list containing the elements with odd index and the second list containing the elements with even index, must be done using fold, here is my attempt:
breakList :: [(Integer, Integer)] -> [[(Integer, Integer)]]
breakList [] = [[], []]
breakList xxs#(x:xs) = foldl (\ acc y -> if length (acc !! 0) < length (acc !! 1) then y : (acc !! 0) else y : (acc !! 1) ) [[], []] xxs
Error I am getting:
Couldn't match type '(Integer, Integer)'
with '[(Integer, Integer)]'
Expected type: [[(Integer, Integer)]]
when hovering over y : (acc !! 1) and y : (acc !! 0)
Example:
Input:
ex1 = [ (2, 2), (1, 3), (2, 3), (2, 4), (3, 5), (0, 2), (2, 1), (1, 4)
, (2, 0), (1, 2), (3, 1), (1, 0)]
Output
breakList ex1
== ( [(2,2),(2,3),(3,5),(2,1),(2,0),(3,1)] , [(1,3),(2,4),(0,2),(1,4),(1,2),(1,0)])
The standard trick here, as hinted at by Willem in the comments, which I first saw few years back on SO in an (F# or Ocaml) answer by [user:Ed'ka], is
evenodds :: [a] -> ([a], [a])
evenodds xs = foldr g ([],[]) xs
where
g x ~(as,bs) = (bs,x:as)
or
oddevens :: [a] -> ([a], [a])
oddevens xs = foldr g ([],[]) xs
where
g x ~(bs,as) = (x:as,bs)
What are odd positions from here, are even positions from the position one notch further on the list.
The tilde ~ introduces a lazy pattern so that the function is properly lazy in its operations.
Note that you want to split a list into two lists of a pair, so the return type should be
([(Integer, Integer)], [(Integer, Integer)])
not
[[(Integer, Integer)]]
and access the element of pair, you can use fst and snd instead of through index, and finally, use foldl will return the resulted list in reversed order, it can be fixed use foldr instead. The correction look like:
breakList :: [(Integer, Integer)]->([(Integer, Integer)], [(Integer, Integer)])
breakList xxs = foldr (\y acc-> if length (fst acc) < length (snd acc)
then (y:(fst acc), snd acc)
else (fst acc, y:(snd acc)) ) ([], []) xxs
I've rewritten the zipWith function using recursion, and now I am trying to rewrite it using list comprehension. I have run into quite a few binding errors and I know that my second line is incorrect. This is the function I have that works like zipWith using recursion:
zipW :: (a -> b -> c) -> [a] -> [b] -> [c]
zipW _ [] _ = []
zipW _ _ [] = []
zipW f (x:xs) (y:ys) = f x y : zipW f xs ys
And this is my attempt to rewrite it as list comprehension:
zipW2 :: (a -> b -> c) -> [a] -> [b] -> [c]
zipW2 f xs ys = [f x y | (x, y) <- zipW2 f xs ys]
I am not sure how to correct the second statement so that it works like zipWith and allows me to choose the operator.
You will need Parallel List Comprehensions extension:
{-# LANGUAGE ParallelListComp #-}
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = [f x y | x <- xs | y <- ys]
The original zipWith has three cases:
when the first list is empty
when the second list is empty
when the neither list is empty
The third case recursively calls zipWith on the tails of the arguments, which does the case analysis again.
In your definition, you only have one case - the list comprehension, so any recursive calls are going to wrap right back to that. And without case analysis, you could loop forever here:
>>> let myZipWith f xs ys = [ f x y | (x,y) <- myZipWith f xs ys ]
>>> myZipWith (,) [] []
^CInterrupted.
Furthermore because you're using f in the recursive call but requiring that the recursive output be a pair, you're placing the implicit requirement that f x y produce a pair:
>>> :t myZipWith
myZipWith :: (t2 -> t3 -> (t2, t3)) -> t -> t1 -> [(t2, t3)]
The solution is to not recurse, but instead to consider each pair directly.
You can use behzad.nouri's solution of enabling the ParallelListComp language extension:
>>> :set -XParallelListComp
>>> let myZipWith f xs ys = [ f x y | x <- xs | y <- ys ]
>>> myZipWith (+) [1,2,4] [0,10,20]
[1,12,24]
ParallelListComp makes the second (and later) vertical pipe characters (|) in a list comprehension legal syntax, stepping through those lists in parallel (zip-like) with earlier lists.
It's good to know how this differs from normal list comprehensions, where you separate each list you draw from with commas. Using commas does nested iteration which is flattened out in the resulting list:
>>> let notZipWith f xs ys = [ f x y | x <- xs, y <- ys ]
>>> notZipWith (+) [1,2,4] [0,10,20]
[1,11,21,2,12,22,4,14,24]
Using the ParallelListComp extension is really just syntatical sugar for the original zipWith, so you may consider it cheating.
You could also just rely on the original zip:
>>> let myZipWith f xs ys = [ f x y | (x,y) <- zip xs ys ]
>>> myZipWith (+) [1,2,4] [0,10,20]
[1,12,24]
But since zip is defined as zipWith (,), that's probably cheating too.
Another way you could go is to use indices:
>>> let myZipWith f xs ys = [ f x y | i <- [0..min (length xs) (length ys) - 1], let x = xs !! i, let y = ys !! i ]
>>> myZipWith (+) [1,2,4] [0,10,20]
[1,12,24]
But this is going to be horrendously inefficient, as !! is a linear-time operation, making myZipWith quadratic, while zipWith is linear:
>>> :set +s
>>> last $ myZipWith (+) (replicate 10000000 1) (replicate 10000000 2)
3
(4.80 secs, 3282337752 bytes)
>>> last $ zipWith (+) (replicate 10000000 1) (replicate 10000000 2)
3
(0.40 secs, 2161935928 bytes)
I'm sure there's other bad ways to create an equivalent to zipWith with a list comprehension, but I'm not terribly convinced that there's a good way, even from the ones above.
Is there any way to swap two elements in a list if the only thing I know about the elements is the position at which they occur in the list.
To be more specific, I am looking for something like this:
swapElementsAt :: Int -> Int -> [Int] -> [Int]
that would behave like that:
> swapElementsAt 1 3 [5,4,3,2,1] -- swap the first and third elements
[3,4,5,2,1]
I thought that a built-in function for this might exists in Haskell but I wasn't able to find it.
Warning: differential calculus. I don't intend this answer entirely seriously, as it's rather a sledgehammer nutcracking. But it's a sledgehammer I keep handy, so why not have some sport? Apart from the fact that it's probably rather more than the questioner wanted to know, for which I apologize. It's an attempt to dig out the deeper structure behind the sensible answers which have already been suggested.
The class of differentiable functors offers at least the following bits and pieces.
class (Functor f, Functor (D f)) => Diff (f :: * -> *) where
type D f :: * -> *
up :: (I :*: D f) :-> f
down :: f :-> (f :.: (I :*: D f))
I suppose I'd better unpack some of those definitions. They're basic kit for combining functors. This thing
type (f :-> g) = forall a. f a -> g a
abbreviates polymorphic function types for operations on containers.
Here are constant, identity, composition, sum and product for containers.
newtype K a x = K a deriving (Functor, Foldable, Traversable, Show)
newtype I x = I x deriving (Functor, Foldable, Traversable, Show)
newtype (f :.: g) x = C {unC :: f (g x)} deriving (Functor, Foldable, Traversable, Show)
data (f :+: g) x = L (f x) | R (g x) deriving (Functor, Foldable, Traversable, Show)
data (f :*: g) x = f x :*: g x deriving (Functor, Foldable, Traversable, Show)
D computes the derivative of a functor by the usual rules of calculus. It tells us how to represent a one-hole context for an element. Let's read the types of those operations again.
up :: (I :*: D f) :-> f
says we can make a whole f from the pair of one element and a context for that element in an f. It's "up", because we're navigating upward in a hierarchical structure, focusing on the whole rather than one element.
down :: f :-> (f :.: (I :*: D f))
Meanwhile, we can decorate every element in a differentiable functor structure with its context, computing all the ways to go "down" to one element in particular.
I'll leave the Diff instances for the basic components to the end of this answer. For lists we get
instance Diff [] where
type D [] = [] :*: []
up (I x :*: (xs :*: ys)) = xs ++ x : ys
down [] = C []
down (x : xs) = C ((I x :*: ([] :*: xs)) :
fmap (id *:* ((x :) *:* id)) (unC (down xs)))
where
(*:*) :: (f a -> f' a) -> (g a -> g' a) -> (f :*: g) a -> (f' :*: g') a
(ff' *:* gg') (f :*: g) = ff' f :*: gg' g
So, for example,
> unC (down [0,1,2])
[I 0 :*: ([] :*: [1,2]),I 1 :*: ([0] :*: [2]),I 2 :*: ([0,1] :*: [])]
picks out each element-in-context in turn.
If f is also Foldable, we get a generalized !! operator...
getN :: (Diff f, Foldable f) => f x -> Int -> (I :*: D f) x
getN f n = foldMap (: []) (unC (down f)) !! n
...with the added bonus that we get the element's context as well as the element itself.
> getN "abcd" 2
I 'c' :*: ("ab" :*: "d")
> getN ((I "a" :*: I "b") :*: (I "c" :*: I "d")) 2
I "c" :*: R ((I "a" :*: I "b") :*: L (K () :*: I "d"))
If we want a functor to offer swapping of two elements, it had better be twice differentiable, and its derivative had better be foldable too. Here goes.
swapN :: (Diff f, Diff (D f), Foldable f, Foldable (D f)) =>
Int -> Int -> f x -> f x
swapN i j f = case compare i j of
{ LT -> go i j ; EQ -> f ; GT -> go j i } where
go i j = up (I y :*: up (I x :*: f'')) where
I x :*: f' = getN f i -- grab the left thing
I y :*: f'' = getN f' (j - 1) -- grab the right thing
It's now easy to grab two elements out and plug them back in the other way around. If we're numbering the positions, we just need to be careful about the way removing elements renumbers the positions.
> swapN 1 3 "abcde"
"adcbe"
> swapN 1 2 ((I "a" :*: I "b") :*: (I "c" :*: I "d"))
(I "a" :*: I "c") :*: (I "b" :*: I "d")
As ever, you don't have do dig down too far below a funny editing operation to find some differential structure at work.
For completeness. Here are the other instances involved in the above.
instance Diff (K a) where -- constants have zero derivative
type D (K a) = K Void
up (_ :*: K z) = absurd z
down (K a) = C (K a)
instance Diff I where -- identity has unit derivative
type D I = K ()
up (I x :*: K ()) = I x
down (I x) = C (I (I x :*: K ()))
instance (Diff f, Diff g) => Diff (f :+: g) where -- commute with +
type D (f :+: g) = D f :+: D g
up (I x :*: L f') = L (up (I x :*: f'))
up (I x :*: R g') = R (up (I x :*: g'))
down (L f) = C (L (fmap (id *:* L) (unC (down f))))
down (R g) = C (R (fmap (id *:* R) (unC (down g))))
instance (Diff f, Diff g) => Diff (f :*: g) where -- product rule
type D (f :*: g) = (D f :*: g) :+: (f :*: D g)
up (I x :*: (L (f' :*: g))) = up (I x :*: f') :*: g
up (I x :*: (R (f :*: g'))) = f :*: up (I x :*: g')
down (f :*: g) = C (fmap (id *:* (L . (:*: g))) (unC (down f))
:*: fmap (id *:* (R . (f :*:))) (unC (down g)))
instance (Diff f, Diff g) => Diff (f :.: g) where -- chain rule
type D (f :.: g) = (D f :.: g) :*: D g
up (I x :*: (C f'g :*: g')) = C (up (I (up (I x :*: g')) :*: f'g))
down (C fg) = C (C (fmap inner (unC (down fg)))) where
inner (I g :*: f'g) = fmap wrap (unC (down g)) where
wrap (I x :*: g') = I x :*: (C f'g :*: g')
Haskell doesn't have such a function, mainly because it is a little bit un-functional. What are you actually trying to achieve?
You can implement your own version of it (maybe there is a more idiomatic way to write this). Note that I assume that i < j, but it would be trivial to extend the function to correctly handle the other cases:
swapElementsAt :: Int -> Int -> [a] -> [a]
swapElementsAt i j xs = let elemI = xs !! i
elemJ = xs !! j
left = take i xs
middle = take (j - i - 1) (drop (i + 1) xs)
right = drop (j + 1) xs
in left ++ [elemJ] ++ middle ++ [elemI] ++ right
There are several working answers here, but I thought that a more idiomatic haskell example would be useful.
In essence, we zip an infinite sequence of natural numbers with the original list to include ordering information in the first element of the resulting pairs, and then we use a simple right fold (catamorphism) to consume the list from the right and create a new list, but this time with the correct elements swapped. We finally extract all the second elements, discarding the first element containing the ordering.
The indexing in this case is zero-based (congruent with Haskell's typical indexes) and the pointers must be in range or you'll get an exception (this can be easily prevented if you change the resulting type to Maybe [a]).
swapTwo :: Int -> Int -> [a] -> [a]
swapTwo f s xs = map snd . foldr (\x a ->
if fst x == f then ys !! s : a
else if fst x == s then ys !! f : a
else x : a) [] $ ys
where ys = zip [0..] xs
And a single liner, doing the swap in just one pass (combining the functionality of the foldr and map into a zipWith):
swapTwo' f s xs = zipWith (\x y ->
if x == f then xs !! s
else if x == s then xs !! f
else y) [0..] xs
That's how I solved it:
swapElementsAt :: Int -> Int -> [a] -> [a]
swapElementsAt a b list = list1 ++ [list !! b] ++ list2 ++ [list !! a] ++ list3
where list1 = take a list;
list2 = drop (succ a) (take b list);
list3 = drop (succ b) list
Here I used the convention that position 0 is the first. My function expects a<=b.
What I like most in my program is the line take a list.
Edit: If you want to get more such cool lines, look at this code:
swapElementsAt :: Int -> Int -> [a] -> [a]
swapElementsAt a another list = list1 ++ [list !! another] ++ list2 ++ [list !! a] ++ list3
where list1 = take a list;
list2 = drop (succ a) (take another list);
list3 = drop (succ another) list
first-order one-pass swapping
swap 1 j l = let (jth,ith:l') = swapHelp j l ith in jth:l'
swap j 1 l = swap 1 j l
swap i j (h:t) = h : swap (i-1) (j-1) t
swapHelp 1 (h:t) x = (h,x:t)
swapHelp n (h:t) x = (y,h:t') where
(y, t') = swapHelp (n-1) t x
now with precondition in compliance with original question, i.e. relaxed to 1 <= i,j <= length l for swap i j l
draws heavily on an idea by #dfeuer to reduce the problem to swapping the 1st element of a list with another from a given position
This is a strange thing to do, but this should work, aside from the off-by-one errors you'll have to fix since I'm writing this on my phone. This version avoids going over the same segments of the list any more times than necessary.
swap' :: Int -> Int -> [a] -> [a]
swap' first second lst = beginning ++ [y] ++ middle ++ [x] ++ end
where
(beginning, (x : r)) = splitAt first lst
(middle, (y : end)) = splitAt (second - first - 1) r
swap x y | x == y = id
| otherwise = swap' (min x y) (max x y)
There is also a recursive solution:
setElementAt :: a -> Int -> [a] -> [a]
setElementAt a 0 (_:tail) = a:tail
setElementAt a pos (b:tail) = b:(setElementAt a (pred pos) tail)
swapElementsAt :: Int -> Int -> [a] -> [a]
swapElementsAt 0 b list#(c:tail) = (list !! b):(setElementAt c (pred b) tail)
swapElementsAt a b (c:tail) = c:(swapElementsAt (pred a) (pred b) tail)
I really like #dfeuer 's solution. However there's still room for optimization by way of deforestation:
swap' :: Int -> Int -> [a] -> [a]
swap' first second lst = beginning $ [y] ++ (middle $ [x] ++ end)
where
(beginning, (x : r)) = swapHelp first lst
(middle, (y : end)) = swapHelp (second - first - 1) r
swapHelp :: Int -> [a] -> ([a] -> [a],[a])
swapHelp 0 l = ( id , l)
swapHelp n (h:t) = ((h:).f , r) where
( f , r) = swapHelp (n-1) t
For positional swapping, using a more complex fold function I have changed the value of the smalest (min) index with the value of the greates (xs!!(y-ii)) and then keep the value for the greatest index in the temp, until find it, the index(max).
I used min and max to make sure I encounter in proper order the indices otherwise I would have to put more checks and conditions in the folds function.
folds _ _ _ _ [] = []
folds i z y tmp (x:xs)
| i == z = (xs!!(y-ii)):folds ii z y x xs
| i == y = tmp:folds ii z y 0 xs
| otherwise = x:folds ii z y tmp xs
where
ii = i+1
swapElementsAt x y xs = folds 0 a b 0 xs
where
a = min x y
b = max x y
Results
> swapElementsAt 0 1 [1,1,1,3,4,9]
[1,1,1,3,4,9]
> swapElementsAt 0 5 [1,1,1,3,4,9]
[9,1,1,3,4,1]
> swapElementsAt 3 1 [1,1,1,3,4,5]
[1,3,1,1,4,5]
> swapElementsAt 1 3 [1,1,1,3,4,5]
[1,3,1,1,4,5]
> swapElementsAt 5 4 [1,1,1,3,4,5]
[1,1,1,3,5,4]
Efficiency aside, we can do a fully recursive definition with only pattern matching.
swapListElem :: [a] -> Int -> Int -> [a]
-- Get nice arguments
swapListElem xs i j
| (i>= length xs) || (j>=length xs) = error "Index out of range"
| i==j = xs
| i>j = swapListElem xs j i
-- Base case
swapListElem (x:y:xs) 0 1 = (y:x:xs)
-- Base-ish case: If i=0, use i'=1 as a placeholder for j-th element
swapListElem (x:xs) 0 j = swapListElem (swapListElem (x:(swapListElem xs 0 (j-1))) 0 1) 1 j
-- Non-base case: i>0
swapListElem (x:xs) i j = x:(swapListElem xs (i-1) (j-1))