На самом деле, это почти канонический способ индексации списка. Вам нужно добавить в проверку на отрицательные числа
elem_at xs n | n < 0 = error "elem_at: negative index"
И вы можете добавить конкретное совпадение для пустого списка:
elem_at [] _ = error "elem_at: index too large"
И базовый и индуктивный корпус:
elem_at (x:_) 0 = x
elem_at (_:xs) n = elem_at xs (n-1)
и у вас есть определение индексации списка Prelude, оператор (!!)
.
Несколько более эффективная версия может быть получена через рабочую оболочку, переводя тест индекса на верхний уровень.