Контакты

Достижения

Все достижения (21)

Наибольший вклад в теги

Все теги (97)

Лучшие ответы пользователя

Все ответы (127)
  • Шпаргалки/справочники для front-end разработчика?

    У DevDocs есть расширения для Chrome и Firefox, позволяющие читать доки без подключения к интернету. Там много всего, не только фронтенд.
    Ответ написан
  • Что изучать специалисту по информационной безопасности?

    я ни разу не специалист по информационной безопасности, но имхо можно делать упор на одно из трёх:
    1. Системное администрирование с уклоном в безопасность. От этого я вообще далёк, так что ничего не могу сказать.
    2. Поиск уязвимостей в ПО. Учить C/C++ для понимания, какие дыры можно оставить при написании ПО, а дальше язык ассемблера для реверс инжиниринга программ. Ну и там, не знаю, поищите в интернете исходники вирусов, поразбирайтесь.
    3. Поиск уязвимостей в веб-сервисах. Учить какой-нибудь серверный язык (PHP, Python, Ruby и проч.) + JavaScript + SQL + на базовом уровне HTML. Гуглить XSS, SQL injection, DDoS. Если интересен этот вариант, могу пару ссылок подбросить по основам.
    Ответ написан
  • Как привести словесный пример полиморфизма?

    Полиморфизм бывает трёх типов: параметрический, ad-hoc и полморфизм подтипов.

    Параметрический полиморфизм нужен чтобы писать логику, параметризованную типами, реализующими некоторые интерфейсы (вырожденный случай - параметризованные любыми типами). Простейший пример: функция 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)


    Видно, что логика везде примерно одна и та же, сигнатуры совпадают с точностью до параметризванного типа. Вот для этих случаев и нужен ad-hoc полиморфизм:

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


    Мы параметризовали нужную нам логику относительно параметризованного типа f и теперь можем писать реализации для конкретных типов:

    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 b


    Теперь мы можем писать функции, которые работают с любыми функторами, то есть опять-таки сократить повторение логики в коде.

    Наконец, полиморфизм подтипов - это несколько другой подход к предыдущей проблеме. Вместо выделения общего интерфейса мы создаём базовый тип и наследуем от него остальные. В этом случае Functor будет абстрактным классом с абстрактным методом map, от которого наследуются типы Maybe, List и т.д. В таком случае сигнатура функции, принимающей и возвращающей функтор, будет выглядеть примерно так: foo :: Functor Int -> Functor String.
    Ответ написан

Лучшие вопросы пользователя

Все вопросы (25)