Using `length` in different positions seems to have different result

I’m writing my first few functions in Haskell and got stuck on the following:

length1 :: [a] -> Int
length1 (x:xs) = length xs

last1 (x:xs) = xs !! (length1 xs)
last2 (x:xs) = xs !! y
                y = length xs

Using Prelude

last1 [1, 2, 3, 4]
last2 [1, 2, 3, 4]

last1 works but last2 -> *** Exception: Prelude.!!: index too large

I also tried

  • last3 (x:xs) = xs !! length xs
  • last4 (x:xs) = xs !! (length xs)

You are using length in last2, as opposed to length1.

Oh sorry for not being clear. That was the point. I don’t see why I can’t replace length1 xs in last2 with length xs since length1 is defined as length xs.

1 Like

length1 is not the same as length

length1 :: [a] -> Int
length1 (x:xs) = length xs

(x:xs) is the «head and tail» pattern match. So:

say you have this list: [1,2,3,4]
`x` will be boung to 1
`xs` will be bound to  [2,3,4]

so you are effectively discarding the head of the list and then computing its legnth.

λ> length [1,2,3,4]
λ> length1 [1,2,3,4]

Makes sense?

Yes, thank you! I didn’t realize I was decapitating the array’s head. This works and what I was originally trying to write.

last2 :: [a] -> a
last2 xs = xs !! y
          y = length xs - 1
1 Like