Какую функциональность вы получаете бесплатно с Functors или другими типами классов? - PullRequest
11 голосов
/ 09 января 2012

Я прочитал статью , в которой говорилось:

Предоставление экземпляров для многих стандартных классов типов [Functors] немедленно предоставит вам множество функциональных возможностей практически бесплатно

Мой вопрос: что это за функциональность, которую вы получаете бесплатно (для функторов или других типов классов)?Я знаю, что такое определение функтора, но что я получу за free , определив что-то как функтор / другой тип-класс.Что-то кроме красивого синтаксиса.В идеале это были бы общие и полезные функции, которые работают с функторами / другими типами классов.

Мое воображение (может быть ошибочным) того, что свободные средства - это функции такого рода: TypeClass x => useful x y = ..

== Edit / Additition ==

Полагаю, я в основном спрашиваю о более абстрактных (и ошеломляющих) типовых классах, подобных тем, которые есть в на этом изображении .Для менее абстрактных классов, таких как Ord, моя объектно-ориентированная интуиция понимает.

Ответы [ 6 ]

9 голосов
/ 09 января 2012

Функторы просты и, вероятно, не лучший пример. Давайте вместо этого посмотрим на монады:

  • liftM - если что-то является монадой, это также функтор, где liftM равно fmap.
  • >=>, <=<: вы можете бесплатно создавать a -> m b функции, где m - ваша монада.
  • foldM, mapM, filterM ... вы получаете набор утилитарных функций, которые обобщают существующие функции для использования вашей монады.
  • when, guard* и unless - вы также получаете некоторые функции управления бесплатно.
  • join - это на самом деле довольно существенно для определения монады, но вам не нужно определять его в Haskell, так как вы определили >>=.
  • трансформаторов - ErrorT и прочее. Вы можете прикрепить обработку ошибок к вашему новому типу бесплатно (дай или возьми)!

По сути, вы получаете широкий спектр стандартных функций, «поднятых» для использования вашего нового типа, как только вы сделаете его экземпляром Monad. Также становится тривиальным (но, увы, не автоматическим) сделать его Functor и Applicative.

Однако это все «симптомы» более общей идеи. Вы можете написать интересный, нетривиальный код, который применяется к всем монадам. Вы можете найти некоторые функции, которые вы написали для вашего типа - которые полезны в вашем конкретном случае, по любой причине - могут быть обобщены для всех монад. Теперь вы можете внезапно взять свою функцию и использовать ее в парсерах, списках, майбах и ...

* Как любезно отметил Даниэль Фишер, guard требует MonadPlus вместо Monad.

5 голосов
/ 09 января 2012

Функторы сами по себе не очень интересны, но они являются необходимой ступенькой для проникновения в аппликативные функторы и Traversables.

Основное свойство, которое делает аппликативные функторы полезными, заключается в том, что вы можете использовать fmap с аппликативным оператором <*>, чтобы «поднять» любую функцию любой арности для работы с аппликативными значениями. То есть Вы можете превратить любой a -> b -> c -> d в Applicative f => f a -> f b -> f c -> f d. Вы также можете взглянуть на Data.Traversable и Data.Foldable, которые содержат несколько функций общего назначения с аппликативными функторами.

Alternative - это специализированный аппликативный функтор, который поддерживает выбор между альтернативами, которые могут «потерпеть неудачу» (точное значение «пусто» зависит от аппликативного экземпляра). Аппликативные парсеры являются одним из практических примеров, когда определения some и many очень интуитивны (например, соответствуют некоторому шаблону ноль или более раз или один или более раз).

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

Monoid - это еще один класс типов, который одновременно прост и полезен. Он в основном определяет способ сложения двух частей данных, который затем дает вам общий concat, а также функциональность в вышеупомянутом модуле Foldable, и также позволяет использовать Writer монада с типом данных.

4 голосов
/ 09 января 2012

Да, это означает, что реализация класса типов Foo дает вам все остальные функции, которые имеют ограничение Foo "бесплатно".

Класс Functor не слишком интересен в этом отношении, поскольку он не дает вам много.

Лучшим примером являются монады и функции в модуле Control.Monad. Как только вы определили две Monad функции (>>=) и return для вашего типа, вы получите еще около тридцати функций, которые затем можно будет использовать в вашем типе.

Вот некоторые из наиболее полезных: mapM, sequence, forever, join, foldM, filterM, replicateM, when, unless и liftM , Они все время отображаются в коде на Haskell.

4 голосов
/ 09 января 2012

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

В качестве примера, реализация класса типов Ord позволит вам использовать такие вещи, как sort, min, max и т. Д. Где в противном случае вам понадобится sortBy и тому подобное.

2 голосов
/ 09 января 2012

Как уже говорили другие, сам Functor на самом деле не дает вам много бесплатно. По сути, чем более высокоуровневым или общим является класс типов (то есть чем больше вещей соответствует этому описанию), тем меньше «бесплатных» функций вы получите. Так, например, Functor и Monoid не предоставляют вам много, но Monad и Arrow предоставляют вам множество полезных функций бесплатно.

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

1 голос
/ 19 января 2012

Ваша объектно-ориентированная интуиция переносится, если вы читаете «интерфейс и реализация» для «класс типов и экземпляр».Если вы сделаете свой новый тип C экземпляром стандартного класса типов B, вы получите бесплатно, что ваш тип будет работать со всем существующим кодом A, который зависит от B.

UML diagram

Как уже говорили другие, когда класс типов является чем-то вроде Monad, бесплатными являются многие библиотечные функции, такие как foldM и when.

...