В настоящее время я изучаю Haskell, и у меня возникла следующая загадка. Что не так со следующей конструкцией?:
zip [1,2,3] [4,5,6]
Result: [(1,4),(2,5),(3,6)]
zipWith (+) [1,2,3] [4,5,6]
Result: [5,7,9]
zipWith (zip) [1,2,3] [4,5,6]
OR
zipWith zip [1,2,3] [4,5,6]
Result: <interactive>:22:1: error:
• No instance for (Num [()]) arising from a use of ‘it’
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
Expected Result: [(1,4),(2,5),(3,6)]
Что мне не хватает?
@NaïmFavier, пожалуйста, уточните, я новичок в этом языке. Что не так с zip [1] [4]?
Ничего, но я не это писал. zipWith zip [1,2,3] [4,5,6] = [zip 1 4, zip 2 5, zip 3 6], но zip работает со списками, а не с числами.
Ах! в этом есть смысл. Итак, zipWith zip [[1],[2],[3]] [[4],[5],[6]] должно работать?
однако это дает другой, хотя и похожий результат: [[(1,4)],[(2,5)],[(3,6)]]
Как я уже сказал, zipWith (,) [1,2,3] [4,5,6]. (Обратите внимание, что zip можно определить как zipWith (,).)





Короче говоря: zip применяется к элементам списков, а не ко всем спискам.
zip — бесполезная функция для объединения двух элементов, не являющихся списками. Действительно, zip имеет тип zip :: [a] -> [b] -> [(a, b)] [Hackage]. Таким образом, он берет два списка и создает из этих списков 2-кортежи.
Это означает, что zipWith будет работать с zip как функция, если у нас есть список списков:
zipWith zip [[1],[2,3]] [[4],[5, 6]] -- [[(1,4)], [(2, 5), (3, 6)]]
здесь внешний zipWith таким образом застегивает внешние структуры, и zip будут вызывать zip [1] [4] и zip [2, 3] [5, 6] для создания [(1, 4)] и [(2, 5), (3, 6)] соответственно.
zip — это ярлык для:
zip = zipWith (,)
действительно, (,) :: a -> b -> (a, b) — это конструктор данных и, следовательно, также функция, которая принимает два элемента и создает кортеж из двух этих двух элементов, поэтому:
zipWith (,) [1, 2, 3] [4, 5, 6] -- [(1, 4), (2, 5), (3, 6)]
объединит два списка вместе.
Так причем здесь No instance for (Num [()]) arising from a use of ‘it’? Или это похоже на мир непонятных сообщений об ошибках LISP?
Когда GHC видит числовой литерал, например 1, он начинает поиск экземпляра Num ожидаемого типа. Если он ожидает Int или Double или что-то в этом роде, все работает так, как задумано. Если он ожидает список, вы получите странное сообщение об отсутствующем экземпляре Num [...]. Здесь GHC ожидал, что 1 будет списком какого-то неопределенного типа (который по умолчанию он решил использовать в качестве единицы AKA ()). Чтобы оценить 1 :: [()], он искал экземпляр Num [()], и поэтому вы получаете странное сообщение об ошибке. Вы можете получить подобные странные сообщения об ошибках с помощью map (*2) 1 или 1+[2].
zipWith (,)сделал бы это.zip 1 4не имеет смысла.