Вопрос

Мне любопытно, как часто опытные программисты на Haskell на практике используют вывод типов. Я часто вижу, что его хвалят как преимущество перед всегда явными объявлениями, необходимыми в некоторых других языках, но по какой-то причине (возможно, только потому, что я новичок) это & Quot; feels & Quot; право писать сигнатуру типа почти все время ... и я уверен, что в некоторых случаях это действительно требуется.

Могут ли некоторые опытные Хаскелеры (Haskellites? Haskellizer?) внести свой вклад?

Это было полезно?

Решение

Это все еще преимущество, даже если вы пишете сигнатуры типов, потому что компилятор будет отлавливать ошибки типов в ваших функциях. Я также обычно пишу сигнатуры типов, но опускаю их в таких местах, как where или let, где вы фактически определяете новые символы, но не чувствуете необходимость указывать сигнатуру типа.

Глупый пример со странным способом вычисления квадратов чисел:

squares :: [Int]
squares = sums 0 odds
  where
    odds = filter odd [1..]
    sums s (a:as) = s : sums (s+a) as

square :: Int -> Int
square n = squares !! n

odds и sums - это функции, которым нужна подпись типа, если компилятор не выведет их автоматически.

Кроме того, если вы используете универсальные функции, как вы обычно делаете, вывод типов - это то, что гарантирует, что вы действительно комбинируете все эти универсальные функции вместе корректным способом. Если вы в вышеприведенном примере скажете

squares :: [a]
squares = ...

Компилятор может сделать вывод, что это недопустимо, потому что одна из используемых функций (функция odd из стандартной библиотеки) должна a находиться в классе типов Integral. В других языках вы обычно узнаете это только позже.

Если вы напишите это как шаблон в C ++, вы получите ошибку компилятора при использовании функции для нецелого типа, но не при определении шаблона. Это может быть довольно запутанным, потому что не сразу понятно, где вы ошиблись, и вам, возможно, придется просмотреть длинную цепочку сообщений об ошибках, чтобы найти реальный источник проблемы. И в чем-то вроде Python вы получаете ошибку во время выполнения в какой-то неожиданный момент, потому что у чего-то не было ожидаемых функций-членов. И даже в более свободно типизированных языках вы можете не получить никаких ошибок, а только неожиданные результаты.

В Haskell компилятор может гарантировать, что функция может быть вызвана со всеми типами, указанными в ее сигнатуре, даже если это универсальная функция, которая действительна для всех типов, которые выполняют некоторые ограничения (классы типов). Это облегчает программирование универсальным способом и использование универсальных библиотек, что намного сложнее понять в других языках. Даже если вы укажете сигнатуру универсального типа, в компиляторе все еще происходит много выводов типов, чтобы выяснить, какой конкретный тип используется в каждом вызове и соответствует ли этот тип всем требованиям функции.

Другие советы

Я всегда пишу сигнатуру типа для функций и значений верхнего уровня, но не для материала в " где " ;, " let " или " do " статьи.

Во-первых, функции верхнего уровня обычно экспортируются, и Хэддоку требуется объявление типа для генерации документации.

Во-вторых, когда вы делаете ошибку, ошибки компилятора намного легче декодировать, если у компилятора есть информация о типе. На самом деле иногда в сложном & Quot; where & Quot; предложение Я получаю непонятную ошибку типа, поэтому я добавляю временные объявления типов, чтобы найти проблему, немного похоже на уровень отладки printf.

Поэтому, чтобы ответить на исходный вопрос, я часто использую вывод типов, но не в 100% случаев.

У тебя хорошие инстинкты. Поскольку они проверяются компилятором, сигнатуры типов для значений верхнего уровня предоставляют бесценную документацию.

Как и другие, я почти всегда ставлю сигнатуру типа для функции верхнего уровня, и почти никогда не для любой другой декларации.

Другой вывод типа места неоценим в интерактивном цикле (например, с GHCi). Этот метод наиболее полезен, когда я разрабатываю и отлаживаю какую-то необычную новую функцию более высокого порядка или что-то подобное.

Когда вы сталкиваетесь с ошибкой проверки типа, хотя компилятор Haskell предоставляет информацию об ошибке, эту информацию может быть сложно декодировать. Чтобы сделать это проще, вы можете закомментировать сигнатуру типа функции, а затем посмотреть, что компилятор сделал вывод о типе, и посмотреть, чем он отличается от вашего предполагаемого типа.

Другое применение - это когда вы создаете «внутреннюю функцию» внутри функции верхнего уровня, но вы не знаете, как создать внутреннюю функцию или даже какой она должна быть. Что вы можете сделать, это передать внутреннюю функцию в качестве аргумента функции верхнего уровня, а затем спросить ghci о типе функции уровня типа. Это будет включать в себя тип внутренней функции. Затем вы можете использовать такой инструмент, как Hoogle, чтобы проверить, существует ли эта функция в библиотеке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top