Рубрика:
Программирование /
Экспертное мнение
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
Дмитрий Сошников: «F# – компромисс между академическим миром и реальной жизнью»
На вопросы «Системного администратора» отвечает технический евангелист Microsoft
Функциональное программирование (ФП) в последнее время переживает небывалый бум популярности, мы решили обсудить феномен этой относительно новой парадигмы с одним из самых известных специалистов по функциональному программированию в России – Дмитрием Сошниковым.
|
Досье |
Дмитрий Сошников, координатор академических программ департамента стратегических технологий, технологический евангелист Microsoft Russia. К.ф.-м.н., доцент, автор нескольких книг и множества научных статей. Евангелист и учитель по призванию – преподает в МАИ и НИУ ВШЭ, уверен, что студентам необходимо дать возможность изучать функциональное программирование и вообще любые альтернативные парадигмы. В качестве хобби изучает фокусы, любит проводить для друзей китайские чайные церемонии, увлекается фотографией. |
Дмитрий не только автор книг и научный сотрудник ряда московских вузов, преподающий на эту тему, но и технический евангелист Microsoft, который лично знаком со многими мировыми светилами ФП. Именно потому мы говорим прежде всего о F# как наиболее сбалансированной и современной реализации этой парадигмы программирования, широко доступной в рамках популярной MS Visual Studio.
– Дмитрий, как представитель Microsoft не могли бы вы рассказать об истории создания F#? Почему и откуда взялась идея функционального программирования, все-таки F# смотрится в Visual Studio особняком. Хотелось бы понять ход мысли и видение ситуации Microsoft, когда компания задумала реализацию такого необычного решения.
– Одна из прелестей .NET состоит в возможности комбинировать различные языки программирования, которые могут взаимодействовать между собой в рамках одной системы или проекта – при этом все языки используют единую систему типов, базовую библиотеку и т.д. Потому для .NET существуют реализации многих языков программирования. Первые функциональные языки для .NET стали появляться еще в первой половине 2000-х: например, SML.NET, были попытки сделать Haskell для .NET.
В какой-то момент аналогичное желание более плотно поэкспериментировать с реализацией функциональных языков на .NET возникло и в Microsoft Research, появился исследовательский проект F#. То, что F# превратился в продукт и вошел в состав Visual Studio, во многом заслуга его создателя, Дона Сайма. Это как раз тот случай, когда нельзя недооценивать роль личности в истории!
Дон был известен тем, что сделал блестящую реализацию Generics для C# и .NET, поэтому он имел достаточное влияние, чтобы превратить исследовательский проект в полноценный продукт, сделав F# одним из базовых языков в составе Visual Studio 2010 и более поздних версиях.
Это произошло отчасти потому, что традиционные языки не решают всех вопросов современности. Мы наблюдаем, что из-за распространенности многоядерных процессоров все чаще требуется писать параллельный код. Точно так же в интернет- и облачных системах важно уметь распределить выполнение задачи по параллельным потокам вычислений.
Функциональная парадигма требует заведомо строить программные системы таким образом, что в них нет неявной зависимости по данным, что облегчает их распараллеливание. С помощью традиционных императивных языков очень сложно писать распараллеливаемый код без ошибок.
И, конечно, появляется возможность привлечь сообщество функциональных программистов на платформу .NET – для них отличный шанс реализовать себя, поскольку благодаря F# в любом .NET-проекте можно использовать модули, реализованные функционально.
Еще один аргумент в пользу F# – увеличение объемов данных и необходимости с ними работать. Многие проекты в современном мире включают элементы машинного обучения (например, интернет-магазины), запросы пользователей к программным системам растут, и усложняются решаемые задачи.
Сейчас F# – это уже достаточно зрелый язык, который очень эффективно используется для решения задач обработки данных.
Основная «ниша» языка – на серверной стороне, в облаке, где необходимо иметь возможность легко получать доступ к большим массивам данных (в F# 3.0 такие задачи легко решаются с помощью Type Providers), осуществлять их обработку, в том числе параллельную и асинхронную.
Кроме того, внутри самой Microsoft F# рассматривается как язык-первопроходец, на котором исследуются и обкатываются новые возможности языков.
Например, в F# 2.0 были так называемые asynchronous workflows – конструкции для организации асинхронных и параллельных вычислений. Соответствующие возможности спустя несколько лет появились в C# (конструкции async/await), а в F# 3.0 уже появляются новые фичи – Type Providers.
– Раз уж вы упомянули некоторые новшества, можно ли кратко остановиться на последних наиболее значимых нововведениях в F#, особенно в контексте недавно вышедшей новой Visual Studio 12?
– В новой Visual Studio 2012 поставляется версия языка F# 3.0, в которой одно из основных нововведений – провайдеры типов (Type Providers) и более полная поддержка LINQ.
Провайдеры типов решают серьезную проблему: данные в большинстве источников слабо структурированы, в то время как промышленные языки – со строгой статической типизацией.
Традиционно для доступа к данным, будь то СУБД или веб-сервис, приходится с помощью инструментов генерировать программный код, так называемый data layer.
Однако любая кодогенерация – это всегда плохо! Type Providers позволяют обойтись без этой кодогенерации, предоставляя необходимые типы данных «на лету», подхватывая структуру данных из внешнего описания или схемы. Из-за этого драматически упрощается доступ к всевозможным источникам данных.
Краткая история функционального программирования |
История возникновения этой парадигмы уходит своими корнями в самое начало ХХ века, когда молодой математик и специалист по логике из Принстонского университета Алонзо Черч (Alonzo Church) разработал формально-логическую систему, названную им Лямбда-исчислением.
Говоря более современным языком, эта система представляла собой своеобразный язык программирования для некоей гипотетической машины, технически недоступной по тем временам. Эта диковинная машина в воображении своего создателя работала полностью на функциях, которые, в свою очередь, принимали в качестве своих аргументов другие функции, в ответ также возвращая функцию. Тогда было типичным обозначать некие математические сущности греческими символами, поэтому подобную «сложную функцию», применяемую для множественных вычислений, обозначили буквой лямбда, в силу чего функциональное программирование до сих пор часто называют Лямбда-исчислениями.
Интересна историческая параллель. Точно в это же время состоявший в активной переписке с Алонзо Алан Тьюринг независимо создал свою собственную, альтернативную к модели своего коллеги «концепцию компьютера», позже названную «Машина Тьюринга», которая в свою очередь позволила формализовать понятие алгоритма, что породило императивное программирование. Забавно то, что позже было доказано, что Лямбда-исчисления фактически эквивалентны машине Тьюринга, иначе говоря, в них можно делать все, что доступно и в обычных императивных языках.
Современное функциональное программирование – практическое применение идей, заложенных в машине Алонзо Черча. Это попытка программировать на основании альтернативной парадигмы, в которой функция – базовый и универсальный элемент языка на всех уровнях построения программы.
Например, на низшем уровне функции используются практически для всего: для расчетов, при создании переменных (здесь переменные – это лишь синонимы для выражений) и так далее.
На более высоком логическом уровне построения программ мы опять имеем дело с функциями, которые в этом случае называются функциями высшего порядка (они отчасти напоминают классы в ООП, которые постоянно взаимодействуют друг с другом).
В свою очередь функции высших порядков позволяют использовать каррирование, то есть превращать функции многих переменных в функцию одной переменной.
При такой концептуальной монолитности и логической стройности функциональные языки невероятно выразительны, что и привлекает к ним внимание в наш век «больших и сложных программ». Здесь не понадобятся паттерны проектирования, потому что язык настолько высокоуровневый, что вы изначально программируете сразу в концепциях.
Традиционные языки имеют сложности с организацией модульной структуры, функциональные языки отчасти снимают эти ограничения (в связи с этим хочется сразу подчеркнуть две их главные особенности, которые в первую очередь способствуют повышению модульности – это функции более высокого порядка и ленивые вычисления). Несмотря на то что ныне существует множество функциональных языков, большинство из них демонстрирует общие подходы, расходясь в некоторых деталях их практической реализации. В этом ряду F# пытается сочетать самые сильные стороны функционального подхода, максимально нивелируя его недостатки, при этом стараясь достичь некоего наиболее разумного баланса и универсальности. Для его создания в Microsoft Research были привлечены многие известные в мире функционального программирования люди, создатели целых школ и популярных языков в этой области. Дополнительное сочетание этих преимуществ с возможностями общей для всех других языков из семейства Visual Studio платформы .NET позволило создать и вовсе уникальный по гибкости и возможностям язык, экспериментальный и новаторский во всех смыслах этого слова.
Другими хорошо известными и уже состоявшимися функциональными языками можно назвать, например, Lisp, Scheme, Erlang, OCaml, Haskell, R и XSLT (XML).
В то же время нужно понимать: несмотря на специфичность многих концепций в функциональном программировании, которые в основном чужды чистому императивному программированию, современные языки чаще всего представляют собой гибрид из сразу нескольких парадигм, в симбиозе которых функциональному программированию еще предстоит побороться за свое доминирующее положение. |
– Каковы акценты и особенности в реализации функционального программирования именно в F#? Например, насколько я знаю, у F# очень слабая поддержка пользовательских интерфейсов. Какие вы можете выделить сильные и слабые стороны F#?
– F# – это все-таки мультипарадигмальный язык. На нем можно писать и объектно-ориентированный, и даже императивный коды.
С этой точки зрения он проигрывает по красоте тому же Haskell, так как начинающему программисту иногда проще не полностью следовать функциональному стилю, и язык не может ему этого запретить.
Однако это имеет и свои плюсы – достигается прозрачная интероперабельность с .NET, начинающему программисту, чтобы написать «Hello, world» нет необходимости проникать в дебри и изучать основы теории категорий и монады (как в случае с Haskell).
Вообще F# – это отличный компромисс между «академическим» миром функционального программирования и реальной жизнью. Отчасти поэтому F# вошел в состав Visual Studio, а не Haskell, хотя один из основных авторов Haskell, Саймон Пейтон-Джонс, также работает в Microsoft Research. Можно постепенно начать переводить какие-то части проекта на F#, при этом они будут хорошо взаимодействовать с другим .NET-кодом.
Если сравнивать с другими языками на платформе .NET, у F#, безусловно, есть своя ниша. Действительно, дизайнеры интерфейсов Visual Studio пока поддерживают только C#/VB (хотя есть много успешных примеров создания интерфейсов на F# через Тype Рroviders или WebSharper). F# же эффективно использовать в задачах обработки данных, для написания облачных сервисов и кода, который должен эффективно выполняться в параллельной среде.
– Дмитрий, мне как бывшему программисту приходилось часто слышать однотипный вопрос от коллег: «В чем же преимущество именно функционального дизайна перед классическим объектно-ориентированным?» Например, сугубо на примере C# и F#: язык F# может делать каррирование функций, но и C# это умеет; F# умеет создавать конвейерные вычисления или наборы (tuples), так и C# это может, и так далее. Можете помочь традиционным программистам, пишущим, скажем, на C#, ухватить суть, выделить уникальные прикладные отличия F# из реальной жизни?
– На эту тему есть отличная статья: John Hughes, Why Functional Programming Matters (http://www.cse.chalmers.se/ ~rjmh/Papers/whyfp.pdf). Там приводятся примеры, демонстрирующие, что функции высшего порядка (в том числе использование каррирования функций) и ленивые вычисления могут существенно повлиять на модульность программы, то есть на ее более эффективное разбиение на части. Таким образом, функциональный подход позволяет лучше бороться со сложностью.
Формат интервью не позволяет сильно углубляться в детали, поэтому если просто перечислять списком основные преимущества, ради которых стоит переходить на функциональные языки, то, наверное, получится так.
Первое. Вывод типов – при сохранении строгой статической типизации языка вы будете писать на 80% меньше кода. Вообще функциональные языки позволяют больше думать и меньше писать.
Второе. Отсутствие побочных эффектов, что драматически сокращает количество ошибок и позволяет распараллеливать код.
Третье. Каррирование и функции высшего порядка.
Четвертое. Наличие встроенных в язык и библиотеку богатых средств работы со списками, ленивыми последовательностями, tuples и т.д.
Пятое. Очень мощные средства метапрограммирования – квотирование, монадические выражения и т.д. – при желании вы можете расширить синтаксис языка, введя в него дополнительные конструкции. Например, через монадические выражения реализован отличный механизм параллельного программирования на F#.
Шестое. От функционального программирования вы будете получать удивительное эстетическое удовольствие, как только проникнетесь его духом.
– Тем не менее функциональное программирование не слишком широко используется в массовом, коммерческом, программировании в мире. По крайней мере так было раньше. Изменилось ли что-то сейчас, можете ли вы привести примеры реальных крупных проектов, созданных, например, на F#?
– Действительно, у многих сложилось мнение, что функциональное программирование не очень применимо в реальной жизни. Это заблуждение уходит корнями в те времена, когда появился первый функциональный язык – Lisp.
В конце 1960-х годов это был практически первый язык со «сборкой мусора» – очевидно, по тем временам это казалось чудовищно неэффективным! Сейчас же большинство коммерческих языков использует сборку мусора, и это не кажется пустой тратой ресурсов.
На самом деле с точки зрения производительности F# при умелом программировании практически не уступает другим .NET-языкам, ведь он компилируется в такой же IL-код.
Интерес к функциональным языкам сейчас подогревается еще и тем, что возникает потребность в написании параллельного кода, который мог бы работать эффективно на нескольких ядрах процессора или на нескольких компьютерах в кластере или облаке.
Такой код писать очень сложно, так как человек в своей голове представляет себе только один поток выполнения. Функциональное программирование позволяет сильно упростить написание параллельных программ, поскольку сама парадигма программирования, стиль мышления приводят к независимым по данным алгоритмам.
Как результат – мы видим все больше проектов, реализованных на функциональных языках: F#, Haskell, OCaml, даже Common Lisp. Около года назад меня очень порадовала статья на Habrahabr «Пишем веб-сервер на Common Lisp».
F# сейчас находит широкое применение в финансовой сфере, где требуются обработка данных и принятие решений, а также нужно строить быстрые алгоритмы, способные давать результат как можно в более короткое время, на сайте Microsoft опубликованы некоторые case studies. На MSDN есть хорошая статья (msdn.microsoft.com/en-us/vstudio/gg634701.aspx), где весьма подробно расписаны преимущества использования F# в организациях. Есть проекты, связанные с биоинформатикой, с построением компиляторов и domain-specific languages.
Для создания веб-приложений на F# есть отличная среда WebSharper, которая позволяет писать код и для клиента, и для сервера на одном языке F# – на их сайте есть внушительный список клиентов, использующих эту среду. Внутри Microsoft F# используют в ряде проектов: анализ скиллов игроков для Halo 3, прогнозирование эффективности и таргетирование онлайн-рекламы, анализ кода драйверов в Microsoft DDK.
– Насколько я знаю, существует набор вполне рабочих компиляторов F#, выпущенных на базе открытого проекта Mono. Как относитесь к Open Source вообще и что можете сказать о тамошней реализации F# в частности?
– F# был изначально разработан внутри Microsoft Research в духе открытости, свойственной академическому сообществу. До сих пор параллельно с коммерческой версией F#, входящей в Visual Studio, всегда выходит Open Source-реализация компилятора и библиотек, что позволяет сообществу использовать наш компилятор на других платформах, в том числе в рамках проекта Mono, то есть это не «другая реализация». Для поддержания открытых ресурсов и кода создано F# Software Foundation (http://fsharp.org).
Так что базовая технология F# – компилятор, спецификация, библиотека – распространяется и развивается по принципам Open Source, благодаря этому программисты на разных платформах могут воспользоваться мощным и современным языком, а также внести свой вклад в его развитие и в развитие сообщества.
– Какие общие советы вы могли бы дать, а также какие книги и веб-ресурсы на русском языке порекомендовать нашим читателям, которые хотели бы начать изучать функциональное программирование?
– Традиционно многие программисты боятся изучать функциональное программирование, поскольку думают, что для этого придется читать много теоретического материала. На самом деле это не совсем так, хотя слегка перестраивать мышление все-таки придется. Но это в любом случае окажется полезным, так как вы сможете писать какие-то алгоритмы в функциональном стиле и на других языках!
Для тех, кто любит книги, на русском языке есть две книги по F#. Это подробная переводная книга Криса Смита «Программирования на F#» и более короткая «Функциональное программирование на F#», которую, кстати, написал я. В последней рассказывается не столько о синтаксисе языка, его легко освоить, сколько об основных концепциях функционального программирования, которые позволят вам быстро войти в курс дела.
Кроме того, половина книги – это реальные примеры того, как на F# решать те или иные задачи: запрограммировать веб-сайт или облачный сервис, получить данные из CSV-файла или из СУБД SQL Server, построить графики или приложение Windows Phone, использовать 3D-графику DirectX и т.д. С помощью этих кусочков кода (которые также доступны на www.soshnikov.com/fsharp), вы сможете легко начать решать собственные задачи на F#.
Если же вы хотите найти более академический курс функционального программирования, то на ресурсе intuit.ru есть видеокурс, который я читал в свое время на факультете инноваций и высоких технологий МФТИ, его сейчас продолжаю читать в Высшей школе экономики. А видеопрезентации и демонстрации F# для программистов вы найдете на techdays.ru.
Из полезных англоязычных ресурсов хочу отдельно отметить центральное сообщество fsharp.org – в нем собраны все ссылки на остальные интересные места. Например, там рекомендуется tryfsharp.org – это онлайн-среда программирования на F# прямо из вашего браузера, которой вы можете свободно воспользоваться, если вам не хочется устанавливать F# себе на компьютер, но любопытно попробовать пару примеров.
В сочетании с ней хочется порекомендовать fssnip.net – это большая коллекция коротких фрагментов кода на F#, по которым можно оценить красоту языка и потом использовать в своих проектах.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|