Интересно, почему в статье назвали интерфейсы с default-методами функциональными? Функциональный интерфейс — это просто интерфейс, у которого есть один абстрактный метод, вот и всё. default-методы к функциональности интерфейса непосредственного отношения не имеют.
Спасибо за ссылки, как-то пропустил это в своём кругозоре.
Ну и это же не с пяти метров! И карты, я думаю, всё-таки специальные, в отличие от симок, куда никто не будет вставлять нужную начинку.
Ну бред же. Какое бесконтактное считывание симки, вы что? Это же вполне определённый стандарт, не предусматривающий никакого беспроводного доступа. В банковских картах с чипом что-то похожее, и что, теперь карточки стало можно дистанционно считывать?
Ну а в целом третий миф действительно похож на миф, потому что для достижения критической массы куски урана надо, грубо говоря, сложить вместе. Вспомните, как работали первые атомные бомбы.
Большое спасибо за статью!
К сожалению, очень не хватает информации по разработке плагинов к идее. Никакой полноценной информации по API идеи нет, а лазить в чужом коде и пытаться понять, что там к чему, очень трудно.
Мм, Pentadactyl это эмулятор Vim'а в файрфоксе. В виме gg это стандартная комбинация перехода к началу файла. Также, например, G — это переход к концу страницы)
Выбрал «Не пользуюсь кнопкой наверх, всегда прокручиваю вручную», потому что так делаю на мобильных девайсах. На десктопах у меня Firefox+Pentadactyl, где переход наверх делается комбинацией gg.
Имхо, стоило добавить вариант «Другое»)
Трейдеры готовы тратить сотни миллионов долларов на прокладку кабелей, сокращающих пинг на 6 миллисекунд. Для моделирования финансовых рынков используются суперкомпьютеры, составлением алгоритмов для торговых роботов заняты лучшие математики и программисты мира
Если честно, то на мой взгляд такая ситуация очень печальна. Ведь по сути это бесполезное для общества занятие. Огромные средства и ресурсы вкладываются, фактически, в торговлю воздухом, от которой реальной пользы обществу нет. Сопустствующее этому развитие технологий и науки не является достаточной компенсацией, имхо. Если те же самые ресурсы вкладывать в науку непосредственно, пользы будет многократно больше.
1. Почти. В той статье Map объявлен только для Maybe, а хаскеллевский fmap работает с любым функтором.
2. Это зависит от того, что вы понимаете под «достать» и от вида «коробки». Если вы имеете в виду, можно ли написать функцию вида Monad m => m a -> a, то в общем случае нельзя. Как вы справедливо заметили, из Nothing доставать нечего. А из IO тем более просто так ничего достать не получится, сайд-эффекты во все поля.
Однако для конкретных монад/функторов вполне могут быть доступны возможности извлечь значение из «коробки» либо выполнить какие-нибудь действия, если это невозможно. В любом случае этот процесс «доставания» сведётся к pattern matching, потому что в конечном итоге любой тип данных в хаскелле есть алгебраический тип данных, а для них естественным способом «деконструкции» является как раз паттерн матчинг. Например, ответ на ваш вопрос про Maybe может выглядеть вот так:
someFunction m = case m of
Just v -> ... -- Maybe и в самом деле содержит значение; в этой ветке оно теперь доступно под именем v
Nothing -> ... -- Значения нет, делаем что-то другое, например, используем дефолтное
Однако сила монад и функторов, на самом деле, не непосредственно в возможности извлечь оттуда значение, а в наличии огромного количества комбинаторов. Например, для Maybe существует комбинатор maybe :: b -> (a -> b) -> Maybe a -> b, который определён примерно так:
maybe def f m = case m of
Just v -> f v
Nothing -> def
С его помощью очень удобно обрабатывать Maybe-значения.
Есть общие комбинаторы, вроде >>= и <*>, есть и частные, типа maybe. Они позволяют очень точно, чётко и ясно выражать различные действия внутри монад и функторов.
Любую другую монаду/функтор (кроме IO, но это, понятно, отдельная история), вообще говоря, можно «разобрать» на части с помощью паттернматчинга. Конечно, если автор библиотеки не стал экспортировать конструкторы своей монады/функтора, то пользователи этой библиотеки не смогут её «разобрать» непосредственно, но в таком случае автор, как правило, предоставляет другие возможности получить значение из «контейнера», если это вообще можно сделать в принципе.
Вот тип основной операции аппликативного функтора: (<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
А вот тип основной операции монады (только с другим порядком аргументов): flip (>>=) :: (Monad f) => (a -> f b) -> f a -> f b
Эти операции похожи, но, очевидно, разные. Вторая операция «мощнее» первой, т.е. <*> можно выразить через >>=, а вот наоборот — нет.
Если чуть подробнее, то первая операция работает только с «чистыми» функциями, т. е. в случае аппликативного функтора вы можете совершать над элементами «контейнера» только операции без побочных эффектов (т.е. операции, которые никогда не могут вернуть сам «контейнер»). Монада же позволяет применять к значениям внутри «контейнера» любые операции, в том числе и с побочными эффектами (т.е. возвращающие «контейнер» того же рода).
Если ещё более подробно, то монада позволяет «схлопывать» два уровня «контейнера», т.е. для монад можно определить функцию join :: (Monad m) => m (m a) -> m a
Наличие такой функции, в целом, и обеспечивает возможность применять к значениям в «контейнерах» операции с побочными эффектами. А вот для аппликативных функторов такую функцию определить нельзя.
Пример с Maybe здесь наиболее иллюстративен. Так как Maybe является монадой, то вы можете написать такое (здесь все операции возвращают Maybe):
Причём за счёт свойств монады Maybe, описанных в статье, такая цепочка операций вернёт Nothing, если хотя бы одна операция вернула Nothing. Заметьте, что здесь мы применяем someFailingOperation{3,4} к результатам предыдущих операций.
Если бы Maybe был бы только аппликативным функтором, но не монадой, то такого мы бы написать не смогли: в случае аппликативных функторов функции внутри контекста не могут возвращать сам аппликативный функтор. Вернее, они могут, но тогда мы получим два уровня вложенности контейнеров, а «схлопнуть» их не получится, что делает невозможным их сколько-нибудь осмысленное применение.
При первом запуске демон создаст в «хомяке» директорию .conconky
IMO создавать каталог с конфигурацией в $HOME, когда есть $XDG_CONFIG_HOME = ~/.config не есть хорошо. Есть даже такая библиотека, которая исправляет поведение нехороших программ.
Для справки, третий вариант — значения, зависящие от типов — это просто полиморфизм. Лучше всего это продемонстрировать на языке типа хаскеля. Например, значение (вернее, не значение, а терм) 10 в зависимости от своего типа может быть разным. Например, 10 :: Int даёт целое число 10, 10 :: Double даёт число с плавающей точкой 10.0, 10 :: Complex Double может дать комплексное число 10 + 0i, 10 :: YourType может дать некоторое значение типа YourType, если для этого типа реализован класс типов Num. То есть, в зависимости от того, какой тип мы приписываем литералу (или другому терму, переменной, например), у него будет cвоё значение.
Ваш первый пример зависимого типа правильный, а второй — нет (второй пример ближе к структурным типам, как, например, интерфейсы в Go).
На самом деле, зависимые типы на самом верхнем уровне достаточно простая концепция. Пусть у вас есть тип List<T>. В таком случае тип List можно рассматривать как функцию над типами (вы даёте List тип, например, String, и получаете обратно тоже тип, List<String>). Это типы, параметризованные типами — система \lambda \omega.
Теперь представьте, что вы параметризуете тип не другим типом, а каким-либо значением — числом 10, строкой "string", каким-нибудь объектом. Например, если Vector<N> обозначает список чего-то длиной N, где N — натуральное число: Vector<10>, то тип Vector является зависимым типом. Система типов для лямбда-исчисления, которая позволяет такое делать, и есть \lambda P.
Кстати, K в CMYK так называется, потому что это Key — ключевой цвет. Он может быть и другим, не чёрным.
А светлота — это забавно) Это же brightness — просто яркость.
В целом статья интересная, спасибо.
Да, принцип инверсии контроля очень полезен и, кроме того, справедлив в любых объектно-ориентированных языках. Очень жаль, что очень много программистов про него забывают :( после них приходится такое разгребать, что удивляешься, как это вообще можно было написать, и как готовая программа в принципе работает.
Представьте, гироскоп, и акселерометр, датчик магнитного поля в устройстве за относительно не большие деньги, откуда и зачем такая щедрость?
и зачем такая ювелирная точность? Вряд ли для пользователей, и вряд ли для игр.
Представьте себе, эти качественные датчики сами по себе дешёвые. Цену на них не занижают — это не является «щедростью». А поскольку качественные датчики дешёвые, почему бы производителю планшетов и не поставить качественные датчики? Это просто технический прогресс. А чем лучше датчики, тем лучше работают приложения, их использующие — игры, компасы, шагомеры и прочее.
Приложение сможет создавать фотографии и видеоролики с помощью камеры в любое время без вашего разрешения.
Как вам уже сказали здесь несколько раз, «без вашего разрешения» есть артефакт перевода. Просто так камера смартфона никогда не включится, как и микрофон, как и прочая периферия. Они включаются только тогда, когда этого требует конкретное приложение, причём это приложение обязано продемонстрировать вам, что оно сейчас делает. Снятие данных с камеры без индикации этого невозможно — почитайте документацию для разработчиков Android или исходный код самой системы.
Напомню вам — исходники самой системы Android открытые. Никто бы не допустил возможности того, чего вы так боитесь, в коде системы. От гугла в готовых смартфонах только приложения, такие, как маркет или G+, которые пользуются открытой системой. Они в принципе не способны её обойти.
Немного сомнительное предположение. Почему количество маны на обратное превращение будет совпадать с количеством на прямое превращение?
Книга, конечно же, нужна.
Ну и это же не с пяти метров! И карты, я думаю, всё-таки специальные, в отличие от симок, куда никто не будет вставлять нужную начинку.
это как?
Ну а в целом третий миф действительно похож на миф, потому что для достижения критической массы куски урана надо, грубо говоря, сложить вместе. Вспомните, как работали первые атомные бомбы.
К сожалению, очень не хватает информации по разработке плагинов к идее. Никакой полноценной информации по API идеи нет, а лазить в чужом коде и пытаться понять, что там к чему, очень трудно.
Имхо, стоило добавить вариант «Другое»)
Если честно, то на мой взгляд такая ситуация очень печальна. Ведь по сути это бесполезное для общества занятие. Огромные средства и ресурсы вкладываются, фактически, в торговлю воздухом, от которой реальной пользы обществу нет. Сопустствующее этому развитие технологий и науки не является достаточной компенсацией, имхо. Если те же самые ресурсы вкладывать в науку непосредственно, пользы будет многократно больше.
Тем не менее, видео в посте весьма впечатляют.
Map
объявлен только дляMaybe
, а хаскеллевскийfmap
работает с любым функтором.2. Это зависит от того, что вы понимаете под «достать» и от вида «коробки». Если вы имеете в виду, можно ли написать функцию вида
Monad m => m a -> a
, то в общем случае нельзя. Как вы справедливо заметили, изNothing
доставать нечего. А изIO
тем более просто так ничего достать не получится, сайд-эффекты во все поля.Однако для конкретных монад/функторов вполне могут быть доступны возможности извлечь значение из «коробки» либо выполнить какие-нибудь действия, если это невозможно. В любом случае этот процесс «доставания» сведётся к pattern matching, потому что в конечном итоге любой тип данных в хаскелле есть алгебраический тип данных, а для них естественным способом «деконструкции» является как раз паттерн матчинг. Например, ответ на ваш вопрос про
Maybe
может выглядеть вот так:Однако сила монад и функторов, на самом деле, не непосредственно в возможности извлечь оттуда значение, а в наличии огромного количества комбинаторов. Например, для
Maybe
существует комбинаторmaybe :: b -> (a -> b) -> Maybe a -> b
, который определён примерно так:С его помощью очень удобно обрабатывать
Maybe
-значения.Есть общие комбинаторы, вроде
>>=
и<*>
, есть и частные, типаmaybe
. Они позволяют очень точно, чётко и ясно выражать различные действия внутри монад и функторов.Любую другую монаду/функтор (кроме
IO
, но это, понятно, отдельная история), вообще говоря, можно «разобрать» на части с помощью паттернматчинга. Конечно, если автор библиотеки не стал экспортировать конструкторы своей монады/функтора, то пользователи этой библиотеки не смогут её «разобрать» непосредственно, но в таком случае автор, как правило, предоставляет другие возможности получить значение из «контейнера», если это вообще можно сделать в принципе.(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
А вот тип основной операции монады (только с другим порядком аргументов):
flip (>>=) :: (Monad f) => (a -> f b) -> f a -> f b
Эти операции похожи, но, очевидно, разные. Вторая операция «мощнее» первой, т.е.
<*>
можно выразить через>>=
, а вот наоборот — нет.Если чуть подробнее, то первая операция работает только с «чистыми» функциями, т. е. в случае аппликативного функтора вы можете совершать над элементами «контейнера» только операции без побочных эффектов (т.е. операции, которые никогда не могут вернуть сам «контейнер»). Монада же позволяет применять к значениям внутри «контейнера» любые операции, в том числе и с побочными эффектами (т.е. возвращающие «контейнер» того же рода).
Если ещё более подробно, то монада позволяет «схлопывать» два уровня «контейнера», т.е. для монад можно определить функцию
join :: (Monad m) => m (m a) -> m a
Наличие такой функции, в целом, и обеспечивает возможность применять к значениям в «контейнерах» операции с побочными эффектами. А вот для аппликативных функторов такую функцию определить нельзя.
Пример с
Maybe
здесь наиболее иллюстративен. Так какMaybe
является монадой, то вы можете написать такое (здесь все операции возвращаютMaybe
):или, эквивалентно,
Причём за счёт свойств монады
Maybe
, описанных в статье, такая цепочка операций вернётNothing
, если хотя бы одна операция вернулаNothing
. Заметьте, что здесь мы применяемsomeFailingOperation{3,4}
к результатам предыдущих операций.Если бы
Maybe
был бы только аппликативным функтором, но не монадой, то такого мы бы написать не смогли: в случае аппликативных функторов функции внутри контекста не могут возвращать сам аппликативный функтор. Вернее, они могут, но тогда мы получим два уровня вложенности контейнеров, а «схлопнуть» их не получится, что делает невозможным их сколько-нибудь осмысленное применение.Небольшое замечание:
Type class переводится скорее как «класс типов», тип классов = type of classes же.
IMO создавать каталог с конфигурацией в $HOME, когда есть
$XDG_CONFIG_HOME = ~/.config
не есть хорошо. Есть даже такая библиотека, которая исправляет поведение нехороших программ.10
в зависимости от своего типа может быть разным. Например,10 :: Int
даёт целое число 10,10 :: Double
даёт число с плавающей точкой 10.0,10 :: Complex Double
может дать комплексное число 10 + 0i,10 :: YourType
может дать некоторое значение типаYourType
, если для этого типа реализован класс типовNum
. То есть, в зависимости от того, какой тип мы приписываем литералу (или другому терму, переменной, например), у него будет cвоё значение.На самом деле, зависимые типы на самом верхнем уровне достаточно простая концепция. Пусть у вас есть тип
List<T>
. В таком случае типList
можно рассматривать как функцию над типами (вы даётеList
тип, например,String
, и получаете обратно тоже тип,List<String>
). Это типы, параметризованные типами — система \lambda \omega.Теперь представьте, что вы параметризуете тип не другим типом, а каким-либо значением — числом 10, строкой
"string"
, каким-нибудь объектом. Например, еслиVector<N>
обозначает список чего-то длиной N, где N — натуральное число:Vector<10>
, то типVector
является зависимым типом. Система типов для лямбда-исчисления, которая позволяет такое делать, и есть \lambda P.А светлота — это забавно) Это же brightness — просто яркость.
В целом статья интересная, спасибо.
Представьте себе, эти качественные датчики сами по себе дешёвые. Цену на них не занижают — это не является «щедростью». А поскольку качественные датчики дешёвые, почему бы производителю планшетов и не поставить качественные датчики? Это просто технический прогресс. А чем лучше датчики, тем лучше работают приложения, их использующие — игры, компасы, шагомеры и прочее.
Как вам уже сказали здесь несколько раз, «без вашего разрешения» есть артефакт перевода. Просто так камера смартфона никогда не включится, как и микрофон, как и прочая периферия. Они включаются только тогда, когда этого требует конкретное приложение, причём это приложение обязано продемонстрировать вам, что оно сейчас делает. Снятие данных с камеры без индикации этого невозможно — почитайте документацию для разработчиков Android или исходный код самой системы.
Напомню вам — исходники самой системы Android открытые. Никто бы не допустил возможности того, чего вы так боитесь, в коде системы. От гугла в готовых смартфонах только приложения, такие, как маркет или G+, которые пользуются открытой системой. Они в принципе не способны её обойти.