Haskell - Функтор

Functorв Haskell - это своего рода функциональное представление различных типов, которые можно отображать. Это высокоуровневая концепция реализации полиморфизма. По словам разработчиков Haskell, все типы, такие как List, Map, Tree и т. Д., Являются экземплярами Haskell Functor.

А Functor - это встроенный класс с определением функции вроде -

class Functor f where 
   fmap :: (a -> b) -> f a -> f b

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

В следующем примере мы увидим, как работает Haskell Functor.

main = do  
   print(map (subtract 1) [2,4,8,16])      
   print(fmap (subtract 1) [2,4,8,16])

Здесь мы использовали оба map() и fmap()над списком для операции вычитания. Вы можете заметить, что оба оператора приведут к одному и тому же результату списка, содержащего элементы [1,3,7,15].

Обе функции вызвали другую функцию с именем subtract() чтобы дать результат.

[1,3,7,15]
[1,3,7,15]

Тогда в чем разница между map и fmap? Разница заключается в их использовании. Functor позволяет нам реализовать еще несколько функционалистов в различных типах данных, таких как «просто» и «ничего».

main = do 
   print (fmap  (+7)(Just 10)) 
   print (fmap  (+7) Nothing)

Приведенный выше фрагмент кода даст следующий вывод на терминале:

Just 17
Nothing

Аппликативный функтор

Аппликативный функтор - это обычный функтор с некоторыми дополнительными функциями, предоставляемыми классом аппликативного типа.

Используя Functor, мы обычно сопоставляем существующую функцию с другой функцией, определенной внутри нее. Но нет никакого способа сопоставить функцию, которая определена внутри Functor, с другим Functor. Вот почему у нас есть еще один объект под названиемApplicative Functor. Эта возможность сопоставления реализуется классом Applicative Type, определенным вControlмодуль. Этот класс дает нам только два метода для работы: один -pure а другой <*>.

Ниже приводится определение класса Applicative Functor.

class (Functor f) => Applicative f where   
   pure :: a -> f a   
   (<*>) :: f (a -> b) -> f a -> f b

В соответствии с реализацией мы можем отобразить другой функтор двумя способами: "Pure" и "<*>". «Чистый» метод должен принимать значение любого типа и всегда будет возвращать аппликативный функтор этого значения.

В следующем примере показано, как работает аппликативный функтор -

import Control.Applicative 

f1:: Int -> Int -> Int 
f1 x y = 2*x+y  
main = do  
   print(show $ f1 <$> (Just 1) <*> (Just 2) )

Здесь мы реализовали аппликативные функторы в вызове функции функции f1. Наша программа выдаст следующий результат.

"Just 4"

Моноиды

Все мы знаем, что Haskell определяет все в виде функций. В функциях у нас есть варианты получить наш ввод как вывод функции. Это то, чтоMonoid является.

А Monoid- это набор функций и операторов, вывод которых не зависит от ввода. Возьмем функцию (*) и целое число (1). Теперь, каким бы ни был вход, его выход останется только с тем же номером. То есть, если вы умножите число на 1, вы получите такое же число.

Вот определение моноида Type Class.

class Monoid m where  
   mempty :: m 
   mappend :: m -> m -> m  
   mconcat :: [m] -> m 
   mconcat = foldr mappend mempty

Взгляните на следующий пример, чтобы понять использование Monoid в Haskell.

multi:: Int->Int 
multi x = x * 1 
add :: Int->Int 
add x = x + 0 

main = do  
   print(multi 9)  
   print (add 7)

Наш код выдаст следующий результат -

9
7

Здесь функция "multi" умножает ввод на "1". Точно так же функция «добавить» добавляет к вводу «0». В обоих случаях вывод будет таким же, как и ввод. Следовательно, функции{(*),1} и {(+),0} являются прекрасными примерами моноидов.