Привет! Меня зовут Ксюша, я работаю бэкенд-разработчиком на C# в Контуре. В весеннем семестре я провела курс по функциональному программированию на Haskell для студентов 3 и 4 курса направления ФИИТ (фундаментальная информатика и информационные технологии) в УрФУ и хочу поделиться своим опытом организации и проведения курса.   

С чего всё началось

Как же так вышло, что я пошла рассказывать студентам про монады и трансформеры (не те, которые Attention is all you need!)?

Я сама училась на ФИИТе, и курс по функциональному программированию (ФП) у нас был обязательным, но в наш год не нашли преподавателей, поэтому мы изучали его самостоятельно.

Мне ФП выворачивало мозг! Особенно меня удивил подход с лямбда-калькулятором. Попробуйте проверить число на то, что оно 0, имея только лямбды в распоряжении. А это мы еще про рекурсию не говорили.

isZero = \n.(n (\x.false) true)

И почему вообще булевы значения — это тоже какие-то функции? В общем, мне было это очень интересно, но много материала я не поняла в момент прохождения или плохо научилась применять. Мне помнится, что я поплыла на теме трансформеров и продвинутых монад. Очень хотелось разобраться в концепциях функционального программирования поподробнее, а какой лучший способ разобраться в чем-либо? Объяснить это другому человеку! Вот я и решила преподавать.  

Что представляет из себя курс 

«Введение в функциональное программирование» — это курс в формате перевернутого класса: дома студенты смотрят лекции и решают задачи на платформе ulearn, а потом подключаются на семинар с преподавателем, на котором более подробно разбирается пройденная тема.

Курс знакомит слушателей с концепциями, лежащими под ФП, и тем, как это реализовано в Haskell. Вот полный список тем:

  1. Знакомство с Haskell

  2. Списки

  3. Лямбда-исчисление

  4. Алгебраические типы данных

  5. Типы и полиморфизм в лямбда-исчислении

  6. Ленивые вычисления

  7. Эффекты и монады

  8. Практикум

  9. Классы типов

  10. Структуры данных

  11. Остальные монады

  12. Трансформеры

  13. Тестирование в Haskell

  14. Type-level programming

  15. Пример веб-приложения

Например, вот какую задачу я давала студентам по теме «Трансформеры»: нужно написать функцию, которая проверит, скомпрометирован ли пароль. Звучит просто, не так ведь? 

Однако задача подразумевает чтение базы скомпрометированных паролей (база для простоты является текстовым файлом), а также запись в лог о результате проверки. Все еще звучит просто? Загвоздка в том, что функциональное программирование оперирует чистыми функциями — функциями без сайд-эффектов. А как же тогда нам вообще работать с вводом и выводом? Чтобы дойти до того, чтобы в одной функции осуществить чтение и запись, понадобился почти весь семестр и много изученных концепций из мира функциональщины :)

Так что курс нужен не для обучения промышленной разработке, а для расширения кругозора и общего развития. Чтобы не заучить, как сделать функцию с чтением и записью, а понять, почему она выглядит так, как выглядит, а упростить нельзя.

Математику уже затем учить надо, что она ум в порядок приводит.

(с) Ломоносов М.В.

Здесь что-то похожее — понимание концепций поможет писать код более креативно, выходя за рамки обычного мышления. Если говорить более прагматично, то во время курса можно словить ценное ощущение того, что ты наконец-то понял, откуда и как появились вещи, которыми ты пользовался на постоянке — LINQ, дженерики, а также куууча монад с разным синтаксисом под свой случай (привет, таски!).

Грабли 

Для меня это был первый опыт организации курса и полноценного преподавания. Основы ФП убрали из обязательной программы, но так как лекции были предзаписаны, а материалы для подготовки к семинарам выложены на той же платформе, то мне было с чего начинать.    

Тем не менее я понимала, что курс проводится в пилотном режиме. Идея преподавать родилась у меня в конце календарного года, а в феврале уже начиналась учеба. Мы понимали, что это семестр, на котором мы наступим на разные грабли. О них в основном и пойдет речь дальше)   

Спрос оказался больше 

Сначала нужно было привлечь студентов на курс. Я написала анонс, добавила мемов про ФП, но была уверена, что придет на курс максимум человек 15-20, поэтому не ограничила набор на курс. Ну и чем же это обернулось? На курсе 60 человек и один преподаватель! 

Это я, когда поняла, как будет выглядеть моя весна
Это я, когда поняла, как будет выглядеть моя весна

Ну… не все так плохо. Я знала, что на семинары будет ходить гораздо меньше людей, поэтому за проведение пар не особо волновалась, но вот с домашками была беда. Проверять даже 15 работ в неделю — достаточно тяжело, а это плюсом к тому, что надо самой вспомнить и/или изучить материал (мы же помним, что я пошла преподавать, чтобы разобраться в теме) и подготовиться к паре. 

Мне повезло, потому что мои бывшие однокурсники согласились помогать проверять домашки. Спасибо им! Без них я бы не вывезла уже на второй неделе. В итоге мы разделили студентов примерно поровну и должны были проверять примерно по 15 работ каждый. Но здесь все прошло не так хорошо, как хотелось бы — в середине семестра ребят догнали разные важные вещи. У кого-то это был запланированный отпуск, у кого-то — организация контеста для отбора на стажировку. 

Еще добавлю, что в середине семестра была тема с объемной домашней работой. Вникать в такие работы было тяжело. Ревью на отвали делать совсем не хочется. Как результат, с середины семестра домашки у многих студентов проверялись очень медленно. 

Это был основной минус курса, который отметили студенты. Вывод, который мы сделали: в следующий раз ограничиваем количество проверяемых работ в неделю 10 штуками на человека, следовательно, набор ограничиваем 10 \* количество преподавателей. Скорее всего, нас снова будет четверо, поэтому набор будет 40 человек.   

Спешное начало курса

Т. к. курс стартанул достаточно быстро, то тестового прогона у нас не было. Да и зачем, казалось мне, ведь ровно на этой же платформе, студенты 3-4 года назад сдавали задачи. И все было нормально!

Конечно же, и тут меня ждал сюрприз, а именно — неработающая тестирующая система!

Лямбда-исчисление поджидает нас в первой половине курса
Лямбда-исчисление поджидает нас в первой половине курса

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

Ну тут все просто — ждем, когда разработчики ulearn все пофиксят на своей стороне и спокойно ждем, благо дедлайны можно и немного сдвинуть.

Когда мне написали то же самое в другой день, я уже была на опыте и знала, что буду делать — переложу ответственность на разработчиков ulearn! Но не тут-то было…

Неполадки в первый раз были при сдаче задачи на хаскеле, а вот во второй раз — при сдаче задачи по лямбда-исчислению, для которого мы используем mikrokosmos. Как работает тестирующая система: у задачи есть Dockerfile, из которого собирается образ для тестирования. В нашем случае нужно было установить haskell и mikrokosmos, потому что он написан на haskell. Далее в рабочую директорию копируется решение студента и прогоняются тесты. Вот только образ с микрокосмосом перестал собираться… Оказалось, что используемый образ хаскеля для сборки микрокосмоса устарел и теперь не устанавливается. Ну легко, просто поднимаем версию хаскеля, да и все. Так я и сделала и получила ошибки при компиляции микрокосмоса. В хаскеле сломана обратная совместимость (тред на stackoverflow с такой же проблемой), а значит нужно поднять и версию микрокосмоса. Заходим на страницу этого космического калькулятора, а там последняя версия 0.8.0. А она-то под старую версию и заточена!

Скрин со страницы микрокосмоса на hackage
Скрин со страницы микрокосмоса на hackage

В этот момент я уже совсем было расстроилась: несмотря на то, что локально решения все еще можно было проверить, т.к. был собранный образ на Dockerhub, нужно было бы придумывать, как проверить решения студентов -- перед ревью еще запускать локальный прогон, или временно забить на задачу, или подредактировать регламент курса?

Но внимательный пользователь, а таким оказался Женя, который тоже проверял домашки, зайдет еще дополнительно на гитхаб и увидит, что последняя версия все-таки 0.8.1 и есть Issue для поднятия версии ?

Вот так вот, поигравшись с версиями, у меня получилось пересобрать образ, и студенты смогли сдать задачи на платформе.

Finita la commedia, друзья

Почему так произошло?

Во-первых, я не проверила работоспособность курса, точнее даже не подумала об этом. Впредь буду умнее и предусмотрительнее. Во-вторых, команда ulearn за полгода до запуска курса переустанавливала образы и уже тогда увидела, что образ больше не собирается, но они не нашли, кому об этой проблеме рассказать.

Домашки делают нейросети 

Еще одна проблема, с которой мы столкнулись — использование GPT. Чрезмерное использование GPT. Ооооочень много работ списаны, причем есть и те, которые списаны достаточно неумело — такие работы сразу видно. На ulearn есть система антиплагиата, но все-таки списать можно так, что антиплагиат не сработает.   

Я понимаю, что использование нейросеток неизбежно, поэтому одной из задач, которые нужно будет решить до следующей весны — как адаптировать задачи под их использование? У нас есть несколько идей, как это сделать, но пока они не проработаны.

Если у вас есть опыт адаптации курса под GPT или идеи того, как это сделать, то буду рада, если вы поделитесь ими в комментариях!    

Что получилось хорошо

Что-то я про то, что не получилось… А что же получилось?   

Первые несколько пар мы со студентами работали в общем зале, пытались обсуждать материал и решать небольшие задачки. Но в онлайне люди разговаривали не особо активно, а мне хотелось, чтобы больше людей были вовлечены в процесс. 

Поэтому я внедрила механику с работой в сессионных залах — даю студентам задачки на подумать, но не рокет-сайенс. Они работают над ними в группах по 3-4 человека, а потом мы все собираемся в общем зале, чтобы обсудить решения. 

Может быть, у кого-то получилось изящно реализовать функцию с помощью каких-то библиотечных. Может, у кого-то получилось написать все в одну строчку — всегда интересно посмотреть на то, как одну задачу можно решить разными способами. После этой механики кстати стало подключаться на курсы сильно меньше людей, чем до этого. Зато у нас получилось узнать, кто из студентов пришел на курс, чтобы хорошо разобраться в теме, так что механика получилась успешной. 

Меня очень радовали студенты, которые активничали и общались со мной на парах, у которых получалось докопаться до того, как сделать так, чтобы сошлись типы в функции с трансформерами.   

Мнение самих студентов

Получилось собрать не очень много обратной связи от студентов, но тем не менее курс им, по большей части, понравился. Особенно зашла механика с работой в группах в целом нестандартность курса на фоне «обычного» программирования. Ещё студенты отметили, что курс заставил их поломать голову и подумать в другой плоскости. Я рада, что кому-то понравилось и у меня получилось кого-то заинтересовать!   

Спасибо всем, кто дочитал до конца. Если у вас есть опыт в ФП, а особенно в Haskell, и вам интересно поделиться своим опытом, то буду рада контактам!   

Всем монад)


Воспользуемся моментом и обратимся к тем, у кого есть дети-выпускники, или друзья, которые прямо сейчас выбирают вуз. До 25 июля можно подавать заявления на бюджет. ФИИТ на матмехе УрФУ — отличное ИТ-направление, а Екатеринбург — крутой город для студенческой жизни. Все подробности и нужные ссылки в ВК https://vk.com/fiiturfu. Смело пересылайте знакомым абитуриентам!

Комментарии (9)


  1. tkutru
    22.07.2025 16:54

    Нормальная тема!

    Ксюша, было прикольно если бы ты обрисовала основные идеи курса/ФП в отдельном посте. Тем более что по твоей основной работе бекенд на си шарпе это по идее должен быть сплошной ООП. Как ты докатилась до такого? :) успехов


    1. ksyusha_ast Автор
      22.07.2025 16:54

      Спасибо!

      Хорошая идея насчет статьи, я подумаю)

      А насчет того, как докатилась до такого, тут все просто – мне любопытно разбираться в новых вещах) лямбда-исчисление – вообще сплошная головоломка, когда ты сам задачи пытаешься решать


  1. WhoIsJohnGolt
    22.07.2025 16:54

    Интересная статья, спасибо!

    Я, конечно, уже далеко не студент, но о некотором погружении в ФП тоже иногда подумываю и тоже из интереса. Есть ли какие-то хорошие курсы/книги, с которых стоило бы начать?


    1. ksyusha_ast Автор
      22.07.2025 16:54

      Привет!

      1. Собственно можешь попроходить курс на ulearn. Ты можешь сдавать задачи на автопроверку, но ревью от преподавателя не будет. В каждом разделе есть слайд со ссылками по теме. Я, конечно же, сама все не читала)

      2. Еще есть хорошие лекции на ютубе от чувака, который LINQ писал. Вообще он, конечно, ученый)

      3. Ссылки на пару учебников есть еще здесь

      Резюмируя, я бы начала с курса и дополняла лекциями с ютуба. Для погружения в ФП более чем достаточно будет)


  1. vityo
    22.07.2025 16:54

    А возможно ли где-то посмотреть лекции?


    1. ksyusha_ast Автор
      22.07.2025 16:54

      Да

      1. Можно смотреть лекции на платформе ulearn https://ulearn.me/Course/fpintroduction/Vstuplenie_ce7b15fc-20f6-4f1e-b8eb-29444d0ee3c1, там же можно сдавать задачи на автопроверку.

      2. Если интересуют только лекции, то можно смотреть в ВК видео https://vkvideo.ru/playlist/-9594364_54049377


  1. QweLoremIpsum
    22.07.2025 16:54

    Если вы знакомы с C# то обязательно попробуйте F# , ваша жизнь разделится на до и после...


  1. i-netay
    22.07.2025 16:54

    Приятно, что есть энтузиасты преподавать Haskell. Во вшэ мне этого не дали, даже плюсы, только питон. С необолием версий библиотек, устареванием и неподдержкой новых версий в Haskell, увы, известная больная тема. Доходил до ручной правки исходников библиотек, чтобы компилились. Чтобы курс был менее нишевым, когда только Haskell, можно добавлять менее чистый, но всё же функциональный ещё как Scala.


    1. ksyusha_ast Автор
      22.07.2025 16:54

      Найти преподавателей Haskell очень сложно, это да)
      Про scala — на ФИИТ этот курс тоже можно выбрать. У меня были студенты, которые уже сходили на курс по скале, где больше в практику уклон, а потом пришли ко мне на хаскель, где больше про теорию функ прога. При этом кто-то из прошедших хаскель как первый язык ФП могут потом тоже выбрать скалу.