JavaScript
- 35 ответов
- 0 вопросов
31
Вклад в тег
map, применяющая функцию к каждому элементу массива. Без полиморфизма мы бы писали отдельную функцию для каждого типа:mapIntFloat :: (Int -> Float) -> [Int] -> [Float]
mapIntFloat f [] = []
mapIntFloat f (x:xs) = (f x) : (map f xs)
mapIntString :: (Int -> String) -> [Int] -> [String]
mapIntString f [] = []
mapIntString f (x:xs) = (f x) : (map f xs)
-- и так далееmapTypeType. Чтобы избежать повторения логики, параметризуем функцию map относительно типов исходного массива и массива, получаемого в результате:map :: forall a b. (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x) : (map f xs)Int или Float у нас переменные типов: a и b.map для массивов, применима и к другим типам. Например, к optional-значениям. Без ad-hoc полиморфизма мы напишем что-то типа:mapList :: forall a b. (a -> b) -> [a] -> [b]
mapList f [] = []
mapList f (x:xs) = (f x) : (mapList f xs)
mapMaybe :: forall a b. (a -> b) -> Maybe a -> Maybe b
mapMaybe f Nothing = Nothing
mapMaybe f (Just x) = Just (f x)class Functor f where
map :: (a -> b) -> f a -> f bf и теперь можем писать реализации для конкретных типов:instance Functor Maybe where
map f Nothing = Nothing
map f (Just x) = Just (f x)
instance Functor [] where
map f [] = []
map f (x:xs) = (f x) : (map f xs)map теперь имеет тип:map :: forall f a b. Functor f => (a -> b) -> f a -> f bFunctor будет абстрактным классом с абстрактным методом map, от которого наследуются типы Maybe, List и т.д. В таком случае сигнатура функции, принимающей и возвращающей функтор, будет выглядеть примерно так: foo :: Functor Int -> Functor String.