Что значит "!!" означает в haskell?

На странице Haskell wiki написаны две функции:

Функция 1

fib = (map fib' [0 ..] !!)
    where
      fib' 0 = 0
      fib' 1 = 1
      fib' n = fib (n - 1) + fib (n - 2)

Функция 2

fib x = map fib' [0 ..] !! x
    where
      fib' 0 = 0
      fib' 1 = 1
      fib' n = fib (n - 1) + fib (n - 2)

Что делает "!!" означает?

Ответ 1

На самом деле это труднее читать, тогда сначала казалось бы, что операторы в haskell более общие, чем на других языках.

Первое, что мы все думаем сказать вам, - это посмотреть сами. Если вы еще не знаете о hoogle, настало время ознакомиться с ним. Вы можете попросить либо рассказать вам, что функция делает по имени, либо (и это еще более круто), вы можете указать ему тип функции и предложить предложения о том, какая функция реализует этот тип.

Вот что говорит вам об этой функции (оператор):

(!!) :: [a] -> Int -> a

List index (subscript) operator, starting from 0. It is an 
instance of the more general genericIndex, which takes an index     
of any integral type.

Предположим, что вам нужна помощь в этом. Первая строка сообщает нам, что (!!) - это функция, которая берет список вещей ([a]) и Int затем возвращает вам одну из вещей в списке (a). Описания говорят вам, что он делает. Он предоставит вам элемент списка, проиндексированный Int. Итак, xs !! i работает как xs[i] в Java, C или Ruby.

Теперь нам нужно поговорить о том, как работают операторы в haskell. Я не собираюсь отдать вам все это, но я, по крайней мере, дам вам знать, что здесь есть что-то большее, чем вы столкнетесь с другими языками программирования. Операторы "всегда" принимают два аргумента и возвращают что-то (a -> b -> c). Вы можете использовать их как обычную функцию:

add x y
(+) x y -- same as above

Но по умолчанию вы также можете использовать их между выражениями (слово для этого - "infix" ). Вы также можете сделать обычную работу, например, оператором с backtics:

x + y
x `add` y -- same as above

Что делает первый пример кода, который вы дали (особенно для новых кодеков haskell), состоит в том, что оператор !! используется как функция, а не в типичной позиции оператора (infix). Позвольте мне добавить привязку, чтобы она была яснее:

-- return the ith Fibonacci number
fib :: Int -> Int  -- (actually more general than this but do't worry about it) 
fib i = fibs !! i
    where
      fibs :: [Int]
      fibs = map fib' [0 ..]

      fib' :: Int -> Int
      fib' 0 = 0
      fib' 1 = 1
      fib' n = fib (n - 1) + fib (n - 2)

Теперь вы можете вернуться к примеру 1. Убедитесь, что вы понимаете, что означает map fib' [0 ..].

Мне жаль, что ваш вопрос опустился - проголосовали, потому что, если вы понимаете, что происходит, ответ был бы легко найти, но если вы не знаете о операторах, как о существовании в haskell, очень сложно мысленно проанализируйте приведенный выше код.

Ответ 2

(!!):: [a] → Int → a

Оператор списка индексов (индекс), начиная с 0. Это экземпляр более общего genericIndex, который принимает индекс любого интегрального типа.

Смотрите здесь: http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-List.html#g:16