#haskell #sum
#haskell #сумма
Вопрос:
Меня смущают различия между sum (x,y)
и sum(x,y,z)
. Сигнатура типа sum
, похоже, (Foldable t, Num a) => t a -> a
. Что я получаю, так это то, что он принимает foldable t
и класс типов Num a
. Sum (x, y) всегда выводит y, а sum (x, y, z) выдает ошибку:
"Could not deduce (Foldable ((,,) Integer Integer))
arising from a use of `sum'"
Итак, почему sum (x, y) может выводить что-то по сравнению с sum (x, y, z)
Комментарии:
1. но чтобы ответить на вопрос Haskell, это потому, что пары определяются как экземпляр
Foldable
, а тройки — нет. На самом деле это не имеет большого смысла для меня (как и экземпляр для pairs, который просто игнорирует первый элемент), но так оно и есть.2. Вы хотите попробовать
sum [1,2]
иsum [1,2,3]
.3. Эй, Робин, да, это конкретно проблема haskell. Большое вам спасибо за редактирование тегов. Впервые использую stack overflow.
4. Семантика
n
-кортежа — это семантика единственного значения, хранящегося в контекстеn-1
других значений. Что-то сFoldable
экземпляром должно иметь вид* -> *
, что в случае типов продуктов всегда означает, что первыеn-1
значения эффективно игнорируются.Functor
иFoldable
оба делают это последовательно:fmap ( 1) ('a', 3) == ('a', 4)
, в то время какsum ('a', 3) == 3
. (КаждаяFoldable
функция делает немногим больше, чем извлекает значение из своего контекста.) Для 2-х кортежей экземпляры предназначены для(,) a
, а не(a, b)
; для 3-х кортежей они были бы для(,,) a b
not(a, b, c)
; и т.д.5. @chepner Это верно с формальной точки зрения, но как часто люди на самом деле используют подобные кортежи? (
Writer
иControl.Comonad.Env
в сторону)
Ответ №1:
Как в Python, так и в Haskell, (x,y,z)
является кортежем, тогда как [x,y,z]
это список. Однако, в то время как списки в значительной степени одинаковы на обоих языках, кортежи различны: кортежи Python похожи на списки Python, тогда как в Haskell кортежи — это совершенно другая концепция (РЕДАКТИРОВАТЬ: я был неправ); в Haskell кортежи похожи на записи без имен полей (например, (1, "foo", 'b')
типа (Int, String, Char)
). Таким образом, в Haskell вы не можете суммировать кортежи вообще (поскольку вы не можете гарантировать, что каждое «поле» имеет один и тот же тип), что в основном и Could not deduce Foldable
означает. Однако Foldable
экземпляр в прелюдии действительно существует для двух кортежей! Однако, как прокомментировал @RobinZigmond, это работает не так, как вы могли бы ожидать: поскольку он не может гарантировать, что оба поля одного типа, он просто полностью игнорирует первый элемент:
Prelude> sum (1,2)
2
Комментарии:
1. «списки практически одинаковы на обоих языках» — я бы оспорил это. Списки Haskell являются настоящими «связанными списками», тогда как я почти уверен, что «списки» Python на самом деле являются массивами. (И, следовательно, более эффективные — списки Haskell довольно неэффективны для многих вещей, для которых вы использовали бы списки в Python.)
2. @RobinZigmond Верно. Я имел в виду, что в обоих языках списки используются для одной и той же концепции (списка значений), тогда как кортежи — нет.
3. @bradrn С другой стороны, кортежи используются для одной и той же концепции, списки разные, однако большинство людей используют их одинаково: однородный список элементов.
4. «это не работает должным образом» это работает абсолютно правильно, то, как это работает, просто не совсем то, что ожидает большинство людей.
5. Существует еще один способ, с помощью которого кортежи Haskell и Python ближе друг к другу, чем списки Haskell и Python: кортежи неизменяемы на обоих языках, тогда как списки Python изменяемы, а списки Haskell неизменяемы.